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.

2879 lines
100 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * Module Name: TEXTOUT.c
  4. * Author: Martin Barber
  5. * Date: Jun. 19, 1995
  6. * Purpose: Handle calls to DrvTxtOut
  7. *
  8. * Copyright (c) 1995,1996 Cirrus Logic, Inc.
  9. *
  10. * $Log: X:/log/laguna/nt35/displays/cl546x/TEXTOUT.C $
  11. *
  12. * Rev 1.34 Mar 27 1998 14:47:14 frido
  13. * PDR#11280. In the monospaced font loop there was a problem loading
  14. * the pointer to the next glyph bits. It always got the pointer to the
  15. * previous glyph.
  16. *
  17. * Rev 1.33 Mar 04 1998 15:38:46 frido
  18. * Added new shadow macros.
  19. *
  20. * Rev 1.32 Dec 17 1997 16:42:14 frido
  21. * PDR#10875: There was a GPF inside vMmClipGlyphExpansion and NT
  22. * 3.51 does not handle this very well. It caused the hardware to wait for
  23. * another DWORD which was never send.
  24. *
  25. * Rev 1.31 Dec 10 1997 13:32:20 frido
  26. * Merged from 1.62 branch.
  27. *
  28. * Rev 1.30.1.1 Dec 03 1997 18:12:20 frido
  29. * PDR#11039. Fixed allocation of font cache. In certain cases it would
  30. * allocate too few cells and still use the unallocated cells causing
  31. * corruption.
  32. *
  33. * Rev 1.30.1.0 Nov 18 1997 15:40:16 frido
  34. * Changed a spelling error: RWQUIRE into REQUIRE.
  35. *
  36. * Rev 1.30 Nov 03 1997 10:17:36 frido
  37. * Added REQUIRE and WRITE_STRING macros.
  38. * Removed CHECK_QFREE macros.
  39. *
  40. * Rev 1.29 25 Aug 1997 16:07:24 FRIDO
  41. *
  42. * Fixed lockup in 8-bpp vMmClipGlyphExpansion SWAT7 code.
  43. *
  44. * Rev 1.28 08 Aug 1997 17:24:30 FRIDO
  45. * Added support for new memory manager.
  46. * Added SWAT7 switches for 8-bpp hardware bug.
  47. *
  48. * Rev 1.27 29 Apr 1997 16:28:50 noelv
  49. *
  50. * Merged in new SWAT code.
  51. * SWAT:
  52. * SWAT: Rev 1.7 24 Apr 1997 12:05:38 frido
  53. * SWAT: Fixed a missing "}".
  54. * SWAT:
  55. * SWAT: Rev 1.6 24 Apr 1997 11:22:18 frido
  56. * SWAT: NT140b09 merge.
  57. * SWAT: Changed pfm into pCell for SWAT3 changes.
  58. * SWAT:
  59. * SWAT: Rev 1.5 19 Apr 1997 17:11:02 frido
  60. * SWAT: Added SWAT.h include file.
  61. * SWAT: Fixed a bug in DrvDestroyFont causing hangups in 2nd WB97 pass.
  62. * SWAT:
  63. * SWAT: Rev 1.4 18 Apr 1997 00:34:28 frido
  64. * SWAT: Fixed a merge bug.
  65. * SWAT:
  66. * SWAT: Rev 1.3 18 Apr 1997 00:15:28 frido
  67. * SWAT: NT140b07 merge.
  68. * SWAT:
  69. * SWAT: Rev 1.2 10 Apr 1997 16:02:06 frido
  70. * SWAT: Oops, I allocated the font cache in the wrong size.
  71. * SWAT:
  72. * SWAT: Rev 1.1 09 Apr 1997 17:37:30 frido
  73. * SWAT: New font cache allocation scheme. Allocate from a 'pool' of cells
  74. * SWAT: instead of putting the font cache all over the place.
  75. *
  76. * Rev 1.26 08 Apr 1997 12:32:50 einkauf
  77. *
  78. * add SYNC_W_3D to coordinate MCD/2D hw access
  79. *
  80. * Rev 1.25 21 Mar 1997 13:37:06 noelv
  81. * Added checkes for QFREE.
  82. *
  83. * Rev 1.24 06 Feb 1997 10:38:04 noelv
  84. * Removed WAIT_FOR_IDLE
  85. *
  86. * Rev 1.23 04 Feb 1997 11:11:00 SueS
  87. * Added support for hardware clipping for the 5465.
  88. *
  89. * Rev 1.22 17 Dec 1996 16:59:00 SueS
  90. * Added test for writing to log file based on cursor at (0,0).
  91. *
  92. * Rev 1.21 26 Nov 1996 10:46:36 SueS
  93. * Changed WriteLogFile parameters for buffering.
  94. *
  95. * Rev 1.20 13 Nov 1996 17:01:28 SueS
  96. * Changed WriteFile calls to WriteLogFile.
  97. *
  98. * Rev 1.19 07 Nov 1996 16:10:16 bennyn
  99. *
  100. * Added no offscn mem allocation if DD enabled
  101. *
  102. * Rev 1.18 06 Sep 1996 15:16:44 noelv
  103. * Updated NULL driver for 4.0
  104. *
  105. * Rev 1.17 20 Aug 1996 11:04:36 noelv
  106. * Bugfix release from Frido 8-19-96
  107. *
  108. * Rev 1.3 16 Aug 1996 14:48:20 frido
  109. * Fixed a small wanring error.
  110. *
  111. * Rev 1.2 15 Aug 1996 11:54:32 frido
  112. * Fixed precompiled headers.
  113. *
  114. * Rev 1.1 15 Aug 1996 11:38:32 frido
  115. * Added precompiled header.
  116. *
  117. * Rev 1.0 14 Aug 1996 17:16:32 frido
  118. * Initial revision.
  119. *
  120. * Rev 1.16 25 Jul 1996 15:56:28 bennyn
  121. *
  122. * Modified to support DirectDraw
  123. *
  124. * Rev 1.15 28 May 1996 15:11:36 noelv
  125. * Updated data logging.
  126. *
  127. * Rev 1.14 16 May 1996 15:06:18 bennyn
  128. *
  129. * Added PIXEL_ALIGN to allocoffscnmem()
  130. *
  131. * Rev 1.13 16 May 1996 14:54:32 noelv
  132. * Added logging code.
  133. *
  134. * Rev 1.12 03 May 1996 15:09:42 noelv
  135. *
  136. * Added flag to turn caching on and off.
  137. *
  138. * Rev 1.11 01 May 1996 11:01:48 bennyn
  139. *
  140. * Modified for NT4.0
  141. *
  142. * Rev 1.10 12 Apr 1996 18:13:06 andys
  143. * Fixed bug in combining 3 bytes into DWORD (<< | bug)
  144. *
  145. * Rev 1.9 11 Apr 1996 18:00:56 andys
  146. * Added Code to the > 16 PEL case to guard against walking off the end of a b
  147. *
  148. * Rev 1.8 04 Apr 1996 13:20:32 noelv
  149. * Frido release 26
  150. *
  151. * Rev 1.16 01 Apr 1996 15:29:22 frido
  152. * Fixed bug in font cache when glyph cannot be cached.
  153. *
  154. * Rev 1.15 28 Mar 1996 23:37:34 frido
  155. * Fixed drawing of partially left-clipped glyphs.
  156. *
  157. * Rev 1.14 27 Mar 1996 14:12:18 frido
  158. * Commented changes.
  159. *
  160. * Rev 1.13 25 Mar 1996 11:58:38 frido
  161. * Removed warning message.
  162. *
  163. * Rev 1.12 25 Mar 1996 11:50:42 frido
  164. * Bellevue 102B03.
  165. *
  166. * Rev 1.5 18 Mar 1996 12:34:10 noelv
  167. *
  168. * Added data logging stuff
  169. *
  170. * Rev 1.4 07 Mar 1996 18:24:14 bennyn
  171. *
  172. * Removed read/modify/write on CONTROL reg
  173. *
  174. * Rev 1.3 05 Mar 1996 11:59:20 noelv
  175. * Frido version 19
  176. *
  177. * Rev 1.11 04 Mar 1996 20:23:28 frido
  178. * Cached grCONTROL register.
  179. *
  180. * Rev 1.10 29 Feb 1996 20:23:08 frido
  181. * Changed some comments.
  182. *
  183. * Rev 1.9 28 Feb 1996 22:39:46 frido
  184. * Added Optimize.h.
  185. *
  186. * Rev 1.8 27 Feb 1996 16:38:12 frido
  187. * Added device bitmap store/restore.
  188. *
  189. * Rev 1.7 24 Feb 1996 01:23:16 frido
  190. * Added device bitmaps.
  191. *
  192. * Rev 1.6 03 Feb 1996 13:57:24 frido
  193. * Use the compile switch "-Dfrido=0" to disable my extensions.
  194. *
  195. * Rev 1.5 03 Feb 1996 12:17:58 frido
  196. * Added text clipping.
  197. *
  198. * Rev 1.4 25 Jan 1996 12:45:56 frido
  199. * Added reinitialization of font cache after mode switch.
  200. *
  201. * Rev 1.3 24 Jan 1996 23:10:16 frido
  202. * Moved font cache and entry point to assembly for i386.
  203. *
  204. * Rev 1.2 23 Jan 1996 15:37:20 frido
  205. * Added font cache.
  206. *
  207. \**************************************************************************/
  208. #include "precomp.h"
  209. #include "font.h"
  210. #include "SWAT.h" // SWAT optimizations
  211. #define TEXT_DBG_LEVEL 1
  212. #define TEXT_DBG_LEVEL1 1
  213. #define RECORD_ON FALSE
  214. #define BUFFER_EXPAND FALSE
  215. /*
  216. -------------------------------------------------------------------------------
  217. Module Entry Points:
  218. --------------------
  219. DrvTextOut()
  220. General Plan:
  221. --------------------
  222. *
  223. * On every TextOut, GDI provides an array of 'GLYPHPOS' structures
  224. * for every glyph to be drawn. Each GLYPHPOS structure contains a
  225. * the glyph. (Note that unlike Windows 3.1, which provides a column-
  226. * major glyph bitmap, Windows NT always provides a row-major glyph
  227. * bitmap.) As such, there are three basic methods for drawing text
  228. * with hardware acceleration:
  229. *
  230. * 1) Glyph caching -- Glyph bitmaps are cached by the accelerator
  231. * (probably in off-screen memory), and text is drawn by
  232. * referring the hardware to the cached glyph locations.
  233. *
  234. * 2) Glyph expansion -- Each individual glyph is colour-expanded
  235. * directly to the screen from the monochrome glyph bitmap
  236. * supplied by GDI.
  237. *
  238. * 3) Buffer expansion -- The CPU is used to draw all the glyphs into
  239. * a 1bpp monochrome bitmap, and the hardware is then used
  240. * to colour-expand the result.
  241. *
  242. * The fastest method depends on a number of variables, such as the
  243. * colour expansion speed, bus speed, CPU speed, average glyph size,
  244. * and average string length.
  245. *
  246. * Copyright (c) 1992-1994 Microsoft Corporation
  247. *
  248. \**************************************************************************/
  249. //
  250. // Data logging stuff.
  251. // Gets compiled out in a free bulid.
  252. //
  253. #if LOG_CALLS
  254. char BUF[256];
  255. #if ENABLE_LOG_SWITCH
  256. #define LogFile(x) \
  257. do { \
  258. if (pointer_switch == 1) \
  259. { \
  260. int i = sprintf x ; \
  261. WriteLogFile(ppdev->pmfile, BUF, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex); \
  262. } \
  263. } while(0); \
  264. #else
  265. #define LogFile(x) \
  266. do { \
  267. int i = sprintf x ; \
  268. WriteLogFile(ppdev->pmfile, BUF, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex); \
  269. } while(0); \
  270. #endif
  271. #else
  272. #define BUF 0
  273. #define LogFile(x)
  274. #endif
  275. POINTL gptlZero = { 0, 0 }; // Specifies that the origin of the
  276. // temporary buffer given to the 1bpp
  277. // transfer routine for fasttext is
  278. // at (0, 0)
  279. /******************************Public*Routine******************************\
  280. * void AddToFontCacheChain
  281. *
  282. * Add the FONTCACHE to the Font cache chain
  283. *
  284. \**************************************************************************/
  285. void AddToFontCacheChain(PDEV* ppdev,
  286. FONTOBJ* pfo,
  287. PFONTCACHE pfc)
  288. {
  289. DISPDBG((TEXT_DBG_LEVEL1," AddToFontCacheChain.\n"));
  290. pfc->pfo = pfo;
  291. #if !SWAT3 // We don't need this anymore. The cell grid has all the pointers.
  292. // Hook the font cache into the chain.
  293. if (ppdev->pfcChain != NULL)
  294. {
  295. ppdev->pfcChain->pfcPrev = pfc;
  296. }
  297. pfc->pfcPrev = NULL;
  298. pfc->pfcNext = ppdev->pfcChain;
  299. ppdev->pfcChain = pfc;
  300. #endif
  301. }
  302. /******************************Public*Routine******************************\
  303. * BOOL bIntersect
  304. *
  305. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  306. * the intersection in 'prclResult'. If they don't intersect, has a return
  307. * value of FALSE, and 'prclResult' is undefined.
  308. *
  309. \**************************************************************************/
  310. BOOL bIntersect(
  311. RECTL* prcl1,
  312. RECTL* prcl2,
  313. RECTL* prclResult)
  314. {
  315. DISPDBG((TEXT_DBG_LEVEL1," bIntersect.\n"));
  316. prclResult->left = max(prcl1->left, prcl2->left);
  317. prclResult->right = min(prcl1->right, prcl2->right);
  318. if (prclResult->left < prclResult->right)
  319. {
  320. prclResult->top = max(prcl1->top, prcl2->top);
  321. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  322. if (prclResult->top < prclResult->bottom)
  323. {
  324. return(TRUE);
  325. }
  326. }
  327. return(FALSE);
  328. }
  329. /******************************Public*Routine******************************\
  330. * LONG cIntersect
  331. *
  332. * This routine takes a list of rectangles from 'prclIn' and clips them
  333. * in-place to the rectangle 'prclClip'. The input rectangles don't
  334. * have to intersect 'prclClip'; the return value will reflect the
  335. * number of input rectangles that did intersect, and the intersecting
  336. * rectangles will be densely packed.
  337. *
  338. \**************************************************************************/
  339. LONG cIntersect(
  340. RECTL* prclClip,
  341. RECTL* prclIn, // List of rectangles
  342. LONG c) // Can be zero
  343. {
  344. LONG cIntersections;
  345. RECTL* prclOut;
  346. DISPDBG((TEXT_DBG_LEVEL1," cIntersect.\n"));
  347. cIntersections = 0;
  348. prclOut = prclIn;
  349. for ( ; c != 0; prclIn++, c--)
  350. {
  351. prclOut->left = max(prclIn->left, prclClip->left);
  352. prclOut->right = min(prclIn->right, prclClip->right);
  353. if (prclOut->left < prclOut->right)
  354. {
  355. prclOut->top = max(prclIn->top, prclClip->top);
  356. prclOut->bottom = min(prclIn->bottom, prclClip->bottom);
  357. if (prclOut->top < prclOut->bottom)
  358. {
  359. prclOut++;
  360. cIntersections++;
  361. }
  362. }
  363. }
  364. return(cIntersections);
  365. }
  366. /******************************Public*Routine******************************\
  367. * VOID vClipSolid
  368. *
  369. * Fills the specified rectangles with the specified colour, honouring
  370. * the requested clipping. No more than four rectangles should be passed in.
  371. * Intended for drawing the areas of the opaquing rectangle that extend
  372. * beyond the text box. The rectangles must be in left to right, top to
  373. * bottom order. Assumes there is at least one rectangle in the list.
  374. *
  375. \**************************************************************************/
  376. VOID vClipSolid(
  377. PDEV* ppdev,
  378. LONG crcl,
  379. RECTL* prcl,
  380. ULONG iColor,
  381. CLIPOBJ* pco)
  382. {
  383. BOOL bMore; // Flag for clip enumeration
  384. ENUMRECTS8 ce; // Clip enumeration object
  385. ULONG i;
  386. ULONG j;
  387. #if !(DRIVER_5465 && HW_CLIPPING)
  388. RECTL arclTmp[4];
  389. ULONG crclTmp;
  390. RECTL* prclTmp;
  391. RECTL* prclClipTmp;
  392. LONG iLastBottom;
  393. #endif
  394. RECTL* prclClip;
  395. DISPDBG((TEXT_DBG_LEVEL1,"vClipSolid: Entry.\n"));
  396. ASSERTMSG( (crcl > 0) && (crcl <= 4), "Expected 1 to 4 rectangles");
  397. ASSERTMSG( (pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
  398. "Expected a non-null clip object");
  399. // Do the loop invariant setup here
  400. REQUIRE(2);
  401. LL_DRAWBLTDEF(SOLID_COLOR_FILL, 2);
  402. if (pco->iDComplexity == DC_RECT)
  403. {
  404. crcl = cIntersect(&pco->rclBounds, prcl, crcl);
  405. while (crcl--)
  406. {
  407. REQUIRE(5);
  408. LL_OP0(prcl->left + ppdev->ptlOffset.x,
  409. prcl->top + ppdev->ptlOffset.y);
  410. LL_BLTEXT((prcl->right - prcl->left), (prcl->bottom - prcl->top));
  411. prcl++;
  412. }
  413. }
  414. else // iDComplexity == DC_COMPLEX
  415. {
  416. // Initialize the clip rectangle enumeration to right-down so we can
  417. // take advantage of the rectangle list being right-down:
  418. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
  419. #if DRIVER_5465 && HW_CLIPPING
  420. // Set up the hardware clipping
  421. REQUIRE(6);
  422. LL_DRAWBLTDEF(SOLID_COLOR_FILL | DD_CLIPEN, 0);
  423. i = max(0, prcl->left);
  424. j = max(0, prcl->top);
  425. LL_OP0(i + ppdev->ptlOffset.x, j + ppdev->ptlOffset.y);
  426. LL_BLTEXT_EXT(prcl->right - i, prcl->bottom - j);
  427. do
  428. {
  429. // Get a batch of region rectangles:
  430. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*)&ce);
  431. // Clip the rect list to each region rect:
  432. for (j = ce.c, prclClip = ce.arcl; j-- > 0; prclClip++)
  433. {
  434. // Draw the clipped rects
  435. REQUIRE(5);
  436. LL_CLIPULE(prclClip->left + ppdev->ptlOffset.x,
  437. prclClip->top + ppdev->ptlOffset.y);
  438. LL_CLIPLOR_EX(prclClip->right + ppdev->ptlOffset.x,
  439. prclClip->bottom + ppdev->ptlOffset.y);
  440. } // End for each rectangle in the list.
  441. } while (bMore); // End loop for each batch
  442. #else
  443. // Bottom of last rectangle to fill
  444. iLastBottom = prcl[crcl - 1].bottom;
  445. // Scan through all the clip rectangles, looking for intersects
  446. // of fill areas with region rectangles:
  447. do
  448. {
  449. // Get a batch of region rectangles:
  450. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*)&ce);
  451. // Clip the rect list to each region rect:
  452. for (j = ce.c, prclClip = ce.arcl; j-- > 0; prclClip++)
  453. {
  454. // Since the rectangles and the region enumeration are both
  455. // right-down, we can zip through the region until we reach
  456. // the first fill rect, and are done when we've passed the
  457. // last fill rect.
  458. if (prclClip->top >= iLastBottom)
  459. {
  460. // Past last fill rectangle; nothing left to do:
  461. return;
  462. }
  463. // Do intersection tests only if we've reached the top of
  464. // the first rectangle to fill:
  465. if (prclClip->bottom > prcl->top)
  466. {
  467. // We've reached the top Y scan of the first rect, so
  468. // it's worth bothering checking for intersection.
  469. // Generate a list of the rects clipped to this region
  470. // rect:
  471. prclTmp = prcl;
  472. prclClipTmp = arclTmp;
  473. for (i = crcl, crclTmp = 0; i-- != 0; prclTmp++)
  474. {
  475. // Intersect fill and clip rectangles
  476. if (bIntersect(prclTmp, prclClip, prclClipTmp))
  477. {
  478. // Draw the clipped rects
  479. REQUIRE(5);
  480. LL_OP0(prclClipTmp->left + ppdev->ptlOffset.x,
  481. prclClipTmp->top + ppdev->ptlOffset.y);
  482. LL_BLTEXT ( (prclClipTmp->right - prclClipTmp->left) ,
  483. (prclClipTmp->bottom - prclClipTmp->top) );
  484. }
  485. } // End for each rectangle in the batch.
  486. } // End intersect test.
  487. } // End for each rectangle in the list.
  488. } while (bMore); // End loop for each batch
  489. #endif // if !(DRIVER_5465 && HW_CLIPPING)
  490. } // End DC_COMPLEX
  491. }
  492. #if SWAT7
  493. /******************************Public*Routine******************************\
  494. * VOID Xfer64Pixels
  495. *
  496. * Copy 64 pixels of font data to the Laguna memory.
  497. *
  498. \**************************************************************************/
  499. VOID Xfer64Pixels(
  500. PDEV* ppdev,
  501. UINT x,
  502. UINT y,
  503. UINT bitOffset,
  504. UINT height,
  505. BYTE* pjGlyph,
  506. UINT delta
  507. )
  508. {
  509. delta = (delta + 7) >> 3;
  510. REQUIRE(5);
  511. LL_OP0(x + ppdev->ptlOffset.x, y + ppdev->ptlOffset.y);
  512. LL_BLTEXT(64, height);
  513. while (height--)
  514. {
  515. REQUIRE(3);
  516. LL32(grHOSTDATA[0], *(ULONG*) &pjGlyph[0]);
  517. LL32(grHOSTDATA[1], *(ULONG*) &pjGlyph[4]);
  518. if (bitOffset > 0)
  519. {
  520. LL32(grHOSTDATA[2], pjGlyph[8]);
  521. }
  522. pjGlyph += delta;
  523. }
  524. }
  525. #endif
  526. /******************************Public*Routine******************************\
  527. * VOID vMmClipGlyphExpansion
  528. *
  529. * Handles any strings that need to be clipped, using the 'glyph
  530. * expansion' method.
  531. *
  532. \**************************************************************************/
  533. VOID vMmClipGlyphExpansion(
  534. PDEV* ppdev,
  535. STROBJ* pstro,
  536. CLIPOBJ* pco)
  537. {
  538. BOOL bMoreGlyphs;
  539. ULONG cGlyphOriginal;
  540. ULONG cGlyph;
  541. GLYPHPOS* pgpOriginal;
  542. GLYPHPOS* pgp;
  543. GLYPHBITS* pgb;
  544. POINTL ptlOrigin;
  545. BOOL bMore;
  546. ENUMRECTS8 ce;
  547. RECTL* prclClip;
  548. ULONG ulCharInc;
  549. LONG cxGlyph;
  550. LONG cyGlyph;
  551. BYTE* pjGlyph;
  552. BYTE* pTmp;
  553. LONG cj;
  554. LONG cw;
  555. LONG xLeft;
  556. LONG yTop;
  557. LONG xRight;
  558. LONG yBottom;
  559. LONG xBias;
  560. LONG lDelta;
  561. LONG cx;
  562. LONG cy;
  563. #if SWAT7
  564. UINT xOrigin;
  565. #endif
  566. DISPDBG((TEXT_DBG_LEVEL1,"vMmClipGlyphExpansion: Entry.\n"));
  567. ASSERTMSG(pco != NULL, "Don't expect NULL clip objects here");
  568. do // Loop for each batch of glyphs to be done.
  569. {
  570. //
  571. // Get a batch of glyphs.
  572. //
  573. if (pstro->pgp != NULL)
  574. {
  575. // There's only the one batch of glyphs, so save ourselves
  576. // a call:
  577. pgpOriginal = pstro->pgp;
  578. cGlyphOriginal = pstro->cGlyphs;
  579. bMoreGlyphs = FALSE;
  580. }
  581. else
  582. {
  583. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyphOriginal, &pgpOriginal);
  584. }
  585. //
  586. // cGlyphOrigional is the number of glyphs in the batch before they
  587. // are clipped.
  588. // bMoreGlyphs is TRUE if there are more batches to be done after
  589. // this one.
  590. //
  591. if (cGlyphOriginal > 0) // Were there any glyphs in the batch?
  592. {
  593. ulCharInc = pstro->ulCharInc;
  594. if (pco->iDComplexity == DC_RECT)
  595. {
  596. //
  597. // We could call 'cEnumStart' and 'bEnum' when the clipping is
  598. // DC_RECT, but the last time I checked, those two calls took
  599. // more than 150 instructions to go through GDI. Since
  600. // 'rclBounds' already contains the DC_RECT clip rectangle,
  601. // and since it's such a common case, we'll special case it:
  602. //
  603. bMore = FALSE; // No more clip lists to do.
  604. prclClip = &pco->rclBounds;
  605. ce.c = 1; // Only one rectangle in this list.
  606. goto SingleRectangle;
  607. }
  608. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  609. do // For each list of rectangles.
  610. {
  611. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  612. // For each rectangle in the list.
  613. for (prclClip = &ce.arcl[0]; ce.c != 0; ce.c--, prclClip++)
  614. {
  615. SingleRectangle:
  616. pgp = pgpOriginal;
  617. cGlyph = cGlyphOriginal;
  618. pgb = pgp->pgdf->pgb;
  619. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  620. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  621. // Loop through all the glyphs for this rectangle:
  622. while (TRUE)
  623. {
  624. LogFile((BUF, "GC:M\r\n"));
  625. cxGlyph = pgb->sizlBitmap.cx;
  626. cyGlyph = pgb->sizlBitmap.cy;
  627. pjGlyph = pgb->aj;
  628. #if SWAT7
  629. lDelta = (cxGlyph + 7) >> 3;
  630. #endif
  631. if ((prclClip->left <= ptlOrigin.x) &&
  632. (prclClip->top <= ptlOrigin.y) &&
  633. (prclClip->right >= ptlOrigin.x + cxGlyph) &&
  634. (prclClip->bottom >= ptlOrigin.y + cyGlyph))
  635. {
  636. //-----------------------------------------------------
  637. // Unclipped glyph
  638. #if SWAT7
  639. xOrigin = ptlOrigin.x;
  640. #endif
  641. #if SWAT7
  642. //
  643. // Test for 5465AD hardware bug in 8-bpp.
  644. //
  645. if ( (cxGlyph > 64) && (cxGlyph < 128)
  646. && (ppdev->iBytesPerPixel == 1)
  647. )
  648. {
  649. Xfer64Pixels(ppdev, xOrigin, ptlOrigin.y, 0,
  650. cyGlyph, pjGlyph, cxGlyph);
  651. pjGlyph += 64 / 8;
  652. xOrigin += 64;
  653. cxGlyph -= 64;
  654. }
  655. REQUIRE(5);
  656. LL_OP0(xOrigin + ppdev->ptlOffset.x,
  657. ptlOrigin.y + ppdev->ptlOffset.y);
  658. #else
  659. REQUIRE(5);
  660. LL_OP0(ptlOrigin.x + ppdev->ptlOffset.x,
  661. ptlOrigin.y + ppdev->ptlOffset.y);
  662. #endif
  663. LL_BLTEXT(cxGlyph, cyGlyph);
  664. if (cxGlyph <= 8)
  665. {
  666. //-----------------------------------------------------
  667. // 1 to 8 pels in width
  668. while ( cyGlyph-- )
  669. {
  670. REQUIRE(1);
  671. #if SWAT7
  672. LL32 (grHOSTDATA[0], *pjGlyph);
  673. pjGlyph += lDelta;
  674. #else
  675. LL32 (grHOSTDATA[0], *pjGlyph++);
  676. #endif
  677. }
  678. }
  679. else if (cxGlyph <= 16)
  680. {
  681. //-----------------------------------------------------
  682. // 9 to 16 pels in width
  683. while ( cyGlyph-- )
  684. {
  685. REQUIRE(1);
  686. #if SWAT7
  687. LL32 (grHOSTDATA[0], *(USHORT*)pjGlyph);
  688. pjGlyph += lDelta;
  689. #else
  690. LL32 (grHOSTDATA[0], *((USHORT*)pjGlyph)++);
  691. #endif
  692. }
  693. }
  694. else
  695. {
  696. //-----------------------------------------------------
  697. // More than 16 pels in width
  698. #if SWAT7
  699. cw = (cxGlyph + 31) >> 5;
  700. #else
  701. lDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  702. cw = (lDelta + 3) >> 2;
  703. #endif
  704. pTmp = pjGlyph + lDelta * pgb->sizlBitmap.cy;
  705. for (;cyGlyph!=1; cyGlyph--)
  706. {
  707. WRITE_STRING(pjGlyph, cw);
  708. pjGlyph += lDelta;
  709. }
  710. {
  711. ULONG *pSrc = (ULONG*) pjGlyph + cw - 1;
  712. WRITE_STRING(pjGlyph, cw - 1);
  713. if ((BYTE *)pSrc+4<=pTmp)
  714. {
  715. REQUIRE(1);
  716. LL32 (grHOSTDATA[0], *pSrc++ );
  717. }
  718. else
  719. {
  720. int Extra = (ULONG) pTmp - (ULONG) pSrc;
  721. BYTE * pByte = (BYTE *)pSrc;
  722. ULONG ulData;
  723. DISPDBG((TEXT_DBG_LEVEL1,
  724. "Caught it %s %d %d %x %x\n", __FILE__, __LINE__, Extra, pTmp, pSrc));
  725. if (Extra == 1)
  726. ulData = (ULONG)(*pByte);
  727. else if (Extra == 2)
  728. ulData = (ULONG)(*(USHORT*)pByte);
  729. else
  730. ulData = (((ULONG)*(pByte+2) << 8) | (ULONG)*(pByte+1)) << 8 | *pByte;
  731. REQUIRE(1);
  732. LL32 (grHOSTDATA[0], ulData );
  733. }
  734. }
  735. } // End 16 pels or wider.
  736. } // End unclipped glyph.
  737. else
  738. {
  739. //-----------------------------------------------------
  740. // Clipped glyph
  741. // Find the intersection of the glyph rectangle
  742. // and the clip rectangle:
  743. xLeft = max(prclClip->left, ptlOrigin.x);
  744. yTop = max(prclClip->top, ptlOrigin.y);
  745. xRight = min(prclClip->right, ptlOrigin.x + cxGlyph);
  746. yBottom = min(prclClip->bottom, ptlOrigin.y + cyGlyph);
  747. // Check for trivial rejection:
  748. if (((cx = xRight - xLeft) > 0) &&
  749. ((cy = yBottom - yTop) > 0))
  750. {
  751. xBias = (xLeft - ptlOrigin.x) & 7;
  752. // 'xBias' is the bit position in the monochrome glyph
  753. // bitmap of the first pixel to be lit, relative to
  754. // the start of the byte. That is, if 'xBias' is 2,
  755. // then the first unclipped pixel is represented by bit
  756. // 2 of the corresponding bitmap byte.
  757. //
  758. // Normally, the accelerator expects bit 0 to be the
  759. // first lit byte. We set the host phase to discard the
  760. // first 'xBias' bits.
  761. //
  762. if ( xBias )
  763. {
  764. REQUIRE(2);
  765. LL_OP2_MONO (xBias,0);
  766. }
  767. #if !SWAT7
  768. REQUIRE(5);
  769. LL_OP0(xLeft + ppdev->ptlOffset.x,
  770. yTop + ppdev->ptlOffset.y);
  771. LL_BLTEXT (cx, cy);
  772. #endif
  773. lDelta = (cxGlyph + 7) >> 3;
  774. // compute the end-of-glyph marker before
  775. // clipping the glyph.
  776. pTmp = pjGlyph + lDelta * cy;
  777. pjGlyph += (yTop - ptlOrigin.y) * lDelta
  778. + ((xLeft - ptlOrigin.x) >> 3);
  779. #if SWAT7
  780. //
  781. // Test for 5465AD hardware bug in 8-bpp.
  782. //
  783. if ( (cx > 64) && (cx < 128)
  784. && (ppdev->iBytesPerPixel == 1)
  785. )
  786. {
  787. Xfer64Pixels(ppdev, xLeft, yTop, xBias, cy,
  788. pjGlyph, cxGlyph);
  789. pjGlyph += 64 / 8;
  790. xLeft += 64;
  791. cx -= 64;
  792. }
  793. REQUIRE(5);
  794. LL_OP0(xLeft + ppdev->ptlOffset.x,
  795. yTop + ppdev->ptlOffset.y);
  796. LL_BLTEXT (cx, cy);
  797. #endif
  798. cj = (cx + xBias + 31) >> 5;
  799. for (;cy!=1; cy--)
  800. {
  801. WRITE_STRING(pjGlyph, cj);
  802. pjGlyph += lDelta;
  803. }
  804. {
  805. ULONG *pSrc = (ULONG*) pjGlyph + cj - 1;
  806. int Extra = (ULONG) pTmp - (ULONG) pSrc;
  807. BYTE * pByte = (BYTE *)pSrc;
  808. ULONG ulData;
  809. WRITE_STRING(pjGlyph, cj - 1);
  810. if (Extra == 1)
  811. ulData = (ULONG)(*pByte);
  812. else if (Extra == 2)
  813. ulData = (ULONG)(*(USHORT*)pByte);
  814. else if (Extra == 3)
  815. ulData = (((ULONG)*(pByte+2) << 8) | (ULONG)*(pByte+1)) << 8 | *pByte;
  816. else
  817. ulData = *pSrc;
  818. REQUIRE(1);
  819. LL32 (grHOSTDATA[0], ulData );
  820. }
  821. if (xBias != 0)
  822. {
  823. REQUIRE(2);
  824. LL_OP2_MONO(0,0);
  825. }
  826. } // if not trivially rejected.
  827. } // End clipped glyph.
  828. //
  829. // If we're out of glyphs the get next batch.
  830. if (--cGlyph == 0)
  831. break;
  832. // Get ready for next glyph:
  833. pgp++;
  834. pgb = pgp->pgdf->pgb;
  835. //
  836. // Calculate where to place the next glyph.
  837. // If this is mono spaced text, we may need to
  838. // skip over some pixels to make our characters
  839. // line up.
  840. //
  841. if (ulCharInc == 0)
  842. {
  843. ptlOrigin.x = pgp->ptl.x + pgb->ptlOrigin.x;
  844. ptlOrigin.y = pgp->ptl.y + pgb->ptlOrigin.y;
  845. }
  846. else
  847. {
  848. ptlOrigin.x += ulCharInc;
  849. }
  850. } // End loop for each glyph in the batch.
  851. } // End for each rectangle in the list.
  852. } while (bMore); // Loop for each batch of clipping rectangles.
  853. } // If there were any glyphs in this batch.
  854. } while (bMoreGlyphs); // Loop for each batch of glyphs.
  855. } // End clipped glyph expansion.
  856. /******************************Public*Routine******************************\
  857. * BOOL DrvTextOut
  858. *
  859. * If it's the fastest method, outputs text using the 'glyph expansion'
  860. * method. Each individual glyph is colour-expanded directly to the
  861. * screen from the monochrome glyph bitmap supplied by GDI.
  862. *
  863. * If it's not the fastest method, calls the routine that implements the
  864. * 'buffer expansion' method.
  865. *
  866. \**************************************************************************/
  867. #if (USE_ASM && defined(i386))
  868. BOOL i386DrvTextOut(
  869. #else
  870. BOOL APIENTRY DrvTextOut(
  871. #endif
  872. SURFOBJ* pso,
  873. STROBJ* pstro,
  874. FONTOBJ* pfo,
  875. CLIPOBJ* pco,
  876. RECTL* prclExtra, // If we had set GCAPS_HORIZSTRIKE, we would have
  877. // to fill these extra rectangles (it is used
  878. // largely for underlines). It's not a big
  879. // performance win (GDI will call our DrvBitBlt
  880. // to draw the extra rectangles).
  881. RECTL* prclOpaque,
  882. BRUSHOBJ* pboFore,
  883. BRUSHOBJ* pboOpaque,
  884. POINTL* pptlBrush,
  885. MIX mix)
  886. {
  887. PDEV* ppdev;
  888. BOOL bTextPerfectFit;
  889. ULONG cGlyph;
  890. BOOL bMoreGlyphs;
  891. GLYPHPOS* pgp;
  892. GLYPHBITS* pgb;
  893. BYTE* pjGlyph;
  894. BYTE* pTmp;
  895. #if SWAT7
  896. LONG cxGlyph;
  897. #endif
  898. LONG cyGlyph;
  899. POINTL ptlOrigin;
  900. LONG ulCharInc;
  901. BYTE iDComplexity;
  902. LONG lDelta;
  903. LONG cw;
  904. ULONG iFGColor;
  905. ULONG iBGColor;
  906. ULONG bitCount;
  907. #if SWAT7
  908. UINT xOrigin;
  909. #endif
  910. #if NULL_TEXTOUT
  911. {
  912. if (pointer_switch) return TRUE;
  913. }
  914. #endif
  915. DISPDBG((TEXT_DBG_LEVEL,"DrvTextOut: Entry.\n"));
  916. // The DDI spec says we'll only ever get foreground and background
  917. // mixes of R2_COPYPEN:
  918. ASSERTMSG(mix == 0x0d0d, "GDI should only give us a copy mix");
  919. ppdev = (PDEV*) pso->dhpdev;
  920. SYNC_W_3D(ppdev); // if 3D context(s) active, make sure 3D engine idle before continuing...
  921. if (pso->iType == STYPE_DEVBITMAP)
  922. {
  923. PDSURF pdsurf = (PDSURF)pso->dhsurf;
  924. LogFile((BUF, "DTO Id=%p ", pdsurf));
  925. if (pdsurf->pso)
  926. {
  927. if ( !bCreateScreenFromDib(ppdev, pdsurf) )
  928. {
  929. LogFile((BUF, "DTO: D=DH (punted)\r\n"));
  930. return(EngTextOut(pdsurf->pso, pstro, pfo, pco, prclExtra,
  931. prclOpaque, pboFore, pboOpaque, pptlBrush, mix));
  932. }
  933. else
  934. {
  935. LogFile((BUF, "DTO: D=DF "));
  936. }
  937. }
  938. else
  939. {
  940. LogFile((BUF, "DTO: D=D "));
  941. }
  942. ppdev->ptlOffset.x = pdsurf->ptl.x;
  943. ppdev->ptlOffset.y = pdsurf->ptl.y;
  944. }
  945. else
  946. {
  947. LogFile((BUF, "DTO: D=S "));
  948. ppdev->ptlOffset.x = ppdev->ptlOffset.y = 0;
  949. }
  950. //
  951. // Dump information about the call to the log file.
  952. //
  953. LogFile((BUF, "FG=%X BG=%X ",
  954. pboFore->iSolidColor, pboOpaque->iSolidColor));
  955. LogFile((BUF, "C=%s ",
  956. (pco == NULL) ? "N " :
  957. ((pco->iDComplexity == DC_TRIVIAL) ? "T" :
  958. ((pco->iDComplexity == DC_RECT) ? "R" : "C" ))
  959. ));
  960. LogFile((BUF, "%s ", (prclOpaque != NULL) ? "O" : "T"));
  961. LogFile((BUF, "%s ", (pstro->ulCharInc == 0) ? "P" : "M"));
  962. #if !(USE_ASM && defined(i386))
  963. // If we have a font that is cached but the screen has been reinitialized,
  964. // we delete the font from memory and try again.
  965. if (ppdev->UseFontCache == 0)
  966. pfo->pvConsumer = (VOID*) -1;
  967. if (pfo->pvConsumer != NULL && pfo->pvConsumer != (PVOID) -1)
  968. {
  969. if (((PFONTCACHE) pfo->pvConsumer)->ulFontCount != ppdev->ulFontCount)
  970. {
  971. LogFile((BUF, "FCD "));
  972. DrvDestroyFont(pfo);
  973. }
  974. else
  975. LogFile((BUF, "GC=2 "));
  976. }
  977. if (pfo->pvConsumer == (PVOID) -1)
  978. {
  979. LogFile((BUF, "GC=3"));
  980. }
  981. // If we have a font that has not yet been cached, try caching it.
  982. if (pfo->pvConsumer == NULL)
  983. {
  984. // New font, check it out.
  985. int height = pstro->rclBkGround.bottom - pstro->rclBkGround.top;
  986. LogFile((BUF, "GC="));
  987. #if SWAT3
  988. if (height > FONTCELL_Y * 3 / 2)
  989. #else
  990. if (height > LINES_PER_TILE * 3 / 2)
  991. #endif
  992. {
  993. // Font too big, mark is as uncacheable.
  994. LogFile((BUF, "0size "));
  995. pfo->pvConsumer = (PVOID) -1;
  996. }
  997. else
  998. {
  999. // Allocate memory for the font cache.
  1000. #ifdef WINNT_VER40
  1001. pfo->pvConsumer = MEM_ALLOC(FL_ZERO_MEMORY, sizeof(FONTCACHE), ALLOC_TAG);
  1002. #else
  1003. pfo->pvConsumer = MEM_ALLOC(LMEM_FIXED | LMEM_ZEROINIT, sizeof(FONTCACHE));
  1004. #endif
  1005. if (pfo->pvConsumer == NULL)
  1006. {
  1007. // Not enough memory, mark it as uncacheable.
  1008. LogFile((BUF, "0mem "));
  1009. pfo->pvConsumer = (PVOID) -1;
  1010. }
  1011. else
  1012. {
  1013. LogFile((BUF, "1 "));
  1014. AddToFontCacheChain(ppdev, pfo, pfo->pvConsumer);
  1015. // Store device this font belongs to.
  1016. ((PFONTCACHE) pfo->pvConsumer)->ppdev = ppdev;
  1017. }
  1018. }
  1019. }
  1020. #endif
  1021. // Set FG / BG colors at this level
  1022. iFGColor = pboFore->iSolidColor;
  1023. iBGColor = pboOpaque->iSolidColor;
  1024. switch (ppdev->iBitmapFormat)
  1025. {
  1026. case BMF_8BPP:
  1027. iFGColor |= iFGColor << 8;
  1028. iBGColor |= iBGColor << 8;
  1029. case BMF_16BPP:
  1030. iFGColor |= iFGColor << 16;
  1031. iBGColor |= iBGColor << 16;
  1032. break;
  1033. }
  1034. iDComplexity = (pco == NULL) ? DC_TRIVIAL : pco->iDComplexity;
  1035. #if !(USE_ASM && defined(i386))
  1036. // Can we use the font cache?
  1037. if ( (pfo->pvConsumer != (PVOID) -1) && (iDComplexity != DC_COMPLEX)
  1038. && (((PFONTCACHE) pfo->pvConsumer)->ppdev == ppdev))
  1039. {
  1040. // Set color registers.
  1041. REQUIRE(4);
  1042. LL_BGCOLOR(iBGColor, 2);
  1043. LL_FGCOLOR(iFGColor, 2);
  1044. if (prclOpaque != NULL)
  1045. {
  1046. #if LOG_CALLS
  1047. #define FIT_FLAGS (SO_ZERO_BEARINGS | \
  1048. SO_FLAG_DEFAULT_PLACEMENT | \
  1049. SO_MAXEXT_EQUAL_BM_SIDE | \
  1050. SO_CHAR_INC_EQUAL_BM_BASE)
  1051. bTextPerfectFit =
  1052. (pstro->flAccel & FIT_FLAGS) == FIT_FLAGS;
  1053. if (!(bTextPerfectFit) ||
  1054. (pstro->rclBkGround.top > prclOpaque->top) ||
  1055. (pstro->rclBkGround.left > prclOpaque->left) ||
  1056. (pstro->rclBkGround.right < prclOpaque->right) ||
  1057. (pstro->rclBkGround.bottom < prclOpaque->bottom))
  1058. {
  1059. LogFile((BUF, "FIT=N "));
  1060. }
  1061. else
  1062. {
  1063. LogFile((BUF, "FIT=Y "));
  1064. }
  1065. #endif
  1066. // Draw opaqueing rectangle.
  1067. if (iDComplexity == DC_TRIVIAL)
  1068. {
  1069. REQUIRE(7);
  1070. LL_DRAWBLTDEF(SOLID_COLOR_FILL, 0);
  1071. LL_OP0(prclOpaque->left + ppdev->ptlOffset.x,
  1072. prclOpaque->top + ppdev->ptlOffset.y);
  1073. LL_BLTEXT(prclOpaque->right - prclOpaque->left,
  1074. prclOpaque->bottom - prclOpaque->top);
  1075. }
  1076. else
  1077. {
  1078. LONG x, y, cx, cy;
  1079. x = max(prclOpaque->left, pco->rclBounds.left);
  1080. y = max(prclOpaque->top, pco->rclBounds.top);
  1081. cx = min(prclOpaque->right, pco->rclBounds.right) - x;
  1082. cy = min(prclOpaque->bottom, pco->rclBounds.bottom) - y;
  1083. if ( (cx > 0) && (cy > 0) )
  1084. {
  1085. REQUIRE(7);
  1086. LL_DRAWBLTDEF(SOLID_COLOR_FILL, 0);
  1087. LL_OP0(x + ppdev->ptlOffset.x, y + ppdev->ptlOffset.y);
  1088. LL_BLTEXT(cx, cy);
  1089. }
  1090. }
  1091. }
  1092. // Enable bit swizzling and set DRAWBLTDEF.
  1093. ppdev->grCONTROL |= SWIZ_CNTL;
  1094. LL16(grCONTROL, ppdev->grCONTROL);
  1095. REQUIRE(2);
  1096. LL_DRAWBLTDEF(CACHE_EXPAND_XPAR, 2);
  1097. LogFile((BUF, "UC"));
  1098. LogFile((BUF, "\r\n"));
  1099. // Call the font cache handler.
  1100. if (iDComplexity == DC_TRIVIAL)
  1101. {
  1102. FontCache((PFONTCACHE) pfo->pvConsumer, pstro);
  1103. }
  1104. else
  1105. {
  1106. ClipCache((PFONTCACHE) pfo->pvConsumer, pstro, pco->rclBounds);
  1107. }
  1108. // Disable bit swizzling.
  1109. ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
  1110. LL16(grCONTROL, ppdev->grCONTROL);
  1111. return(TRUE);
  1112. }
  1113. #endif
  1114. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Setting FG/BG Color.\n"));
  1115. REQUIRE(4);
  1116. LL_BGCOLOR(iBGColor, 2);
  1117. LL_FGCOLOR(iFGColor, 2);
  1118. ppdev->grCONTROL |= SWIZ_CNTL;
  1119. LL16(grCONTROL, ppdev->grCONTROL);
  1120. if (prclOpaque != NULL)
  1121. {
  1122. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Setting Opaque.\n"));
  1123. ////////////////////////////////////////////////////////////
  1124. // Opaque Initialization
  1125. ////////////////////////////////////////////////////////////
  1126. //
  1127. // If we paint the glyphs in 'opaque' mode, we may not actually
  1128. // have to draw the opaquing rectangle up-front -- the process
  1129. // of laying down all the glyphs will automatically cover all
  1130. // of the pixels in the opaquing rectangle.
  1131. //
  1132. // The condition that must be satisfied is that the text must
  1133. // fit 'perfectly' such that the entire background rectangle is
  1134. // covered, and none of the glyphs overlap (if the glyphs
  1135. // overlap, such as for italics, they have to be drawn in
  1136. // transparent mode after the opaquing rectangle is cleared).
  1137. //
  1138. #define PERFECT_FIT_FLAGS (SO_ZERO_BEARINGS | \
  1139. SO_FLAG_DEFAULT_PLACEMENT | \
  1140. SO_MAXEXT_EQUAL_BM_SIDE | \
  1141. SO_CHAR_INC_EQUAL_BM_BASE)
  1142. bTextPerfectFit =
  1143. (pstro->flAccel & PERFECT_FIT_FLAGS) == PERFECT_FIT_FLAGS;
  1144. if (!(bTextPerfectFit) ||
  1145. (pstro->rclBkGround.top > prclOpaque->top) ||
  1146. (pstro->rclBkGround.left > prclOpaque->left) ||
  1147. (pstro->rclBkGround.right < prclOpaque->right)||
  1148. (pstro->rclBkGround.bottom < prclOpaque->bottom))
  1149. {
  1150. //
  1151. // Draw opaquing rectangle.
  1152. //
  1153. if (iDComplexity == DC_TRIVIAL)
  1154. {
  1155. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Opaque DC_TRIVIAL.\n"));
  1156. REQUIRE(7);
  1157. LL_DRAWBLTDEF(SOLID_COLOR_FILL, 0);
  1158. LL_OP0(prclOpaque->left + ppdev->ptlOffset.x,
  1159. prclOpaque->top + ppdev->ptlOffset.y);
  1160. LL_BLTEXT ((prclOpaque->right - prclOpaque->left) ,
  1161. (prclOpaque->bottom - prclOpaque->top) );
  1162. }
  1163. else
  1164. {
  1165. vClipSolid(ppdev, 1, prclOpaque, pboOpaque->iSolidColor, pco);
  1166. }
  1167. LogFile((BUF, "FIT=N "));
  1168. // Opaquing rectangle has been drawn, now
  1169. // we do transparent text.
  1170. }
  1171. else
  1172. {
  1173. LogFile((BUF, "FIT=Y "));
  1174. // We don't have to draw the opaquing rectangle because
  1175. // the text is an exact fit.
  1176. goto TextInitOpaque;
  1177. }
  1178. } // End (prclOpaque != NULL)
  1179. LogFile((BUF, "\r\n"));
  1180. ////////////////////////////////////////////////////////////
  1181. // Transparent Initialization
  1182. ////////////////////////////////////////////////////////////
  1183. // Initialize the hardware for transparent text:
  1184. //
  1185. // Set the chip up to do transparent text.
  1186. //
  1187. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Setting XPAR Text.\n"));
  1188. LL_DRAWBLTDEF(TEXT_EXPAND_XPAR, 2);
  1189. goto TextInitDone;
  1190. TextInitOpaque:
  1191. //
  1192. // Set the chip up to do opaque text.
  1193. // Any opaquing rectangle needed has been drawn by now.
  1194. //
  1195. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Setting Opaque Text.\n"));
  1196. LL_DRAWBLTDEF(TEXT_EXPAND_OPAQUE, 2);
  1197. TextInitDone:
  1198. //
  1199. // We're all set up to do either opaque or transparent text.
  1200. // If necessary, any opaquing has been done by now.
  1201. // So let's draw some glyphs on the screen.
  1202. //
  1203. REQUIRE(2);
  1204. LL_OP2_MONO (0,0); // Set Zero phase for transfers
  1205. if (iDComplexity == DC_TRIVIAL)
  1206. {
  1207. do // Loop while there are glyphs to draw.
  1208. {
  1209. //
  1210. // Get a batch of glyphs to draw.
  1211. //
  1212. if (pstro->pgp != NULL)
  1213. {
  1214. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: One batch of Glyphs.\n"));
  1215. // There's only the one batch of glyphs, so save ourselves
  1216. // a call:
  1217. pgp = pstro->pgp;
  1218. cGlyph = pstro->cGlyphs;
  1219. bMoreGlyphs = FALSE;
  1220. }
  1221. else
  1222. {
  1223. DISPDBG((TEXT_DBG_LEVEL1,
  1224. "DrvTextOut: Calling STROBJ_bEnum for Glyphs.\n"));
  1225. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  1226. }
  1227. //
  1228. // cGlyph is the count of glyphs in this batch.
  1229. // bMorGlyphs is TRUE if there is another batch waiting for
  1230. // us after this one.
  1231. //
  1232. if (cGlyph > 0)
  1233. {
  1234. //
  1235. // Check the type of spacing.
  1236. //
  1237. if (pstro->ulCharInc == 0)
  1238. {
  1239. ///////////////////////////////////////////////////////////
  1240. // Proportional Spacing
  1241. DISPDBG((TEXT_DBG_LEVEL1,
  1242. "DrvTextOut: Proportional Spacing.\n"));
  1243. while (TRUE) // Loop once for each Glyph.
  1244. {
  1245. pgb = pgp->pgdf->pgb;
  1246. LogFile((BUF, "GC:M\r\n"));
  1247. #if !SWAT7
  1248. REQUIRE(5);
  1249. LL_OP0(pgp->ptl.x + pgb->ptlOrigin.x + ppdev->ptlOffset.x,
  1250. pgp->ptl.y + pgb->ptlOrigin.y + ppdev->ptlOffset.y);
  1251. LL_BLTEXT (pgb->sizlBitmap.cx, pgb->sizlBitmap.cy);
  1252. #endif
  1253. #if SWAT7
  1254. xOrigin = pgp->ptl.x + pgb->ptlOrigin.x;
  1255. cxGlyph = pgb->sizlBitmap.cx;
  1256. lDelta = (cxGlyph + 7) >> 3;
  1257. #endif
  1258. pjGlyph = pgb->aj;
  1259. cyGlyph = pgb->sizlBitmap.cy;
  1260. #if SWAT7
  1261. //
  1262. // Test for 5465AD hardware bug in 8-bpp.
  1263. //
  1264. if ( (cxGlyph > 64) && (cxGlyph < 128)
  1265. && (ppdev->iBytesPerPixel == 1)
  1266. )
  1267. {
  1268. Xfer64Pixels(ppdev, xOrigin, pgp->ptl.y +
  1269. pgb->ptlOrigin.y, 0, cyGlyph, pjGlyph,
  1270. cxGlyph);
  1271. pjGlyph += 64 / 8;
  1272. xOrigin += 64;
  1273. cxGlyph -= 64;
  1274. }
  1275. REQUIRE(5);
  1276. LL_OP0(xOrigin + ppdev->ptlOffset.x, pgp->ptl.y +
  1277. pgb->ptlOrigin.y + ppdev->ptlOffset.y);
  1278. LL_BLTEXT (cxGlyph, cyGlyph);
  1279. #endif
  1280. // The monochrome bitmap describing the glyph is
  1281. // byte-aligned. This means that if the glyph is
  1282. // 1 to 8 pels in width, each row of the glyph is
  1283. // defined in consecutive bytes; if the glyph is 9
  1284. // to 16 pels in width, each row of the glyph is
  1285. // defined in consecutive words, etc.
  1286. //
  1287. #if SWAT7
  1288. if (cxGlyph <= 8)
  1289. #else
  1290. if (pgb->sizlBitmap.cx <= 8)
  1291. #endif
  1292. {
  1293. //--------------------------------------------------
  1294. // 1 to 8 pels in width
  1295. // 91% of all glyphs will go through this path.
  1296. while (cyGlyph--)
  1297. #if SWAT7
  1298. {
  1299. REQUIRE(1);
  1300. LL32(grHOSTDATA[0], *pjGlyph);
  1301. pjGlyph += lDelta;
  1302. }
  1303. #else
  1304. REQUIRE(1);
  1305. LL32 (grHOSTDATA[0], *pjGlyph++);
  1306. // We're a bit tricky here in order to avoid letting
  1307. // the compiler tail-merge this code (which would
  1308. // add an extra jump):
  1309. pgp++;
  1310. if (--cGlyph != 0)
  1311. continue; // Go do the next glyph.
  1312. break; // Done with all glyphs in this batch.
  1313. // breakout of Glyph Loop.
  1314. #endif
  1315. }
  1316. #if SWAT7
  1317. else if (cxGlyph <= 16)
  1318. #else
  1319. else if (pgb->sizlBitmap.cx <= 16)
  1320. #endif
  1321. {
  1322. //--------------------------------------------------
  1323. // 9 to 16 pels in width
  1324. // 5% of all glyphs will go through this path.
  1325. while ( cyGlyph-- )
  1326. #if SWAT7
  1327. {
  1328. REQUIRE(1);
  1329. LL32(grHOSTDATA[0], *(USHORT*)pjGlyph);
  1330. pjGlyph += lDelta;
  1331. }
  1332. #else
  1333. REQUIRE(1);
  1334. LL32 (grHOSTDATA[0], *((USHORT*)pjGlyph)++);
  1335. #endif
  1336. }
  1337. else
  1338. {
  1339. //--------------------------------------------------
  1340. // More than 16 pels in width
  1341. #if SWAT7
  1342. cw = (cxGlyph + 31) >> 5;
  1343. #else
  1344. lDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  1345. cw = (lDelta + 3) >> 2;
  1346. #endif
  1347. pTmp = pjGlyph + lDelta * pgb->sizlBitmap.cy;
  1348. for (;cyGlyph!=1; cyGlyph--)
  1349. {
  1350. WRITE_STRING(pjGlyph, cw);
  1351. pjGlyph += lDelta;
  1352. }
  1353. {
  1354. ULONG *pSrc = (ULONG*) pjGlyph + cw - 1;
  1355. WRITE_STRING(pjGlyph, cw - 1);
  1356. if ((BYTE *)pSrc+4<=pTmp)
  1357. {
  1358. REQUIRE(1);
  1359. LL32 (grHOSTDATA[0], *pSrc++ );
  1360. }
  1361. else
  1362. {
  1363. int Extra = (ULONG) pTmp - (ULONG) pSrc;
  1364. BYTE * pByte = (BYTE *)pSrc;
  1365. ULONG ulData;
  1366. DISPDBG((TEXT_DBG_LEVEL1,
  1367. "Caught it %s %d %d %x %x\n", __FILE__, __LINE__, Extra, pTmp, pSrc));
  1368. if (Extra == 1)
  1369. ulData = (ULONG)(*pByte);
  1370. else if (Extra == 2)
  1371. ulData = (ULONG)(*(USHORT*)pByte);
  1372. else
  1373. ulData = (((ULONG)*(pByte+2) << 8) | (ULONG)*(pByte+1)) << 8 | *pByte;
  1374. REQUIRE(1);
  1375. LL32 (grHOSTDATA[0], ulData );
  1376. }
  1377. }
  1378. } // END pel width test.
  1379. pgp++; // Next glyph
  1380. if (--cGlyph == 0)
  1381. break; // Done with this batch.
  1382. // Break out of the Glyph Loop.
  1383. } // End Glyph Loop.
  1384. } // End porportional characters.
  1385. else
  1386. {
  1387. ////////////////////////////////////////////////////////////
  1388. // Mono Spacing
  1389. DISPDBG((TEXT_DBG_LEVEL1,"DrvTextOut: Mono Spacing.\n"));
  1390. ulCharInc = pstro->ulCharInc;
  1391. pgb = pgp->pgdf->pgb;
  1392. ptlOrigin.x = pgb->ptlOrigin.x + pgp->ptl.x;
  1393. ptlOrigin.y = pgb->ptlOrigin.y + pgp->ptl.y;
  1394. while (TRUE) // Loop once for each Glyph in the batch.
  1395. {
  1396. LogFile((BUF, "GC:M\r\n"));
  1397. pgb = pgp->pgdf->pgb;
  1398. #if !SWAT7
  1399. REQUIRE(5);
  1400. LL_OP0(ptlOrigin.x + ppdev->ptlOffset.x,
  1401. ptlOrigin.y + ppdev->ptlOffset.y);
  1402. ptlOrigin.x += ulCharInc;
  1403. LL_BLTEXT (pgb->sizlBitmap.cx, pgb->sizlBitmap.cy);
  1404. #endif
  1405. pjGlyph = pgb->aj;
  1406. cyGlyph = pgb->sizlBitmap.cy;
  1407. #if SWAT7
  1408. xOrigin = ptlOrigin.x;
  1409. cxGlyph = pgb->sizlBitmap.cx;
  1410. lDelta = (cxGlyph + 7) >> 3;
  1411. //
  1412. // Test for 5465AD hardware bug in 8-bpp.
  1413. //
  1414. if ( (cxGlyph > 64) && (cxGlyph < 128)
  1415. && (ppdev->iBytesPerPixel == 1)
  1416. )
  1417. {
  1418. Xfer64Pixels(ppdev, xOrigin, ptlOrigin.y, 0,
  1419. cyGlyph, pjGlyph, cxGlyph);
  1420. pjGlyph += 64 / 8;
  1421. xOrigin += 64;
  1422. cxGlyph -= 64;
  1423. }
  1424. REQUIRE(5);
  1425. LL_OP0(xOrigin + ppdev->ptlOffset.x,
  1426. ptlOrigin.y + ppdev->ptlOffset.y);
  1427. ptlOrigin.x += ulCharInc;
  1428. LL_BLTEXT (cxGlyph, cyGlyph);
  1429. #endif
  1430. //
  1431. // Note: Mono spacing does not guarantee that all the
  1432. // glyphs are the same size -- that is, we cannot
  1433. // move the size check out of this inner loop,
  1434. // unless we key off some more of the STROBJ
  1435. // accelerator flags.
  1436. // We are not guarenteed the Glyphs are the same size,
  1437. // only that they are the same distance apart.
  1438. //
  1439. #if SWAT7
  1440. if (cxGlyph <= 8)
  1441. #else
  1442. if (pgb->sizlBitmap.cx <= 8)
  1443. #endif
  1444. {
  1445. //-----------------------------------------------------
  1446. // 1 to 8 pels in width
  1447. while ( cyGlyph-- )
  1448. #if SWAT7
  1449. {
  1450. REQUIRE(1);
  1451. LL32(grHOSTDATA[0], *pjGlyph);
  1452. pjGlyph += lDelta;
  1453. }
  1454. #else
  1455. REQUIRE(1);
  1456. LL32 (grHOSTDATA[0], *pjGlyph++);
  1457. #endif
  1458. }
  1459. #if SWAT7
  1460. else if (cxGlyph <= 16)
  1461. #else
  1462. else if (pgb->sizlBitmap.cx <= 16)
  1463. #endif
  1464. {
  1465. //-----------------------------------------------------
  1466. // 9 to 16 pels in width
  1467. while ( cyGlyph-- )
  1468. #if SWAT7
  1469. {
  1470. REQUIRE(1);
  1471. LL32(grHOSTDATA[0], *(USHORT*)pjGlyph);
  1472. pjGlyph += lDelta;
  1473. }
  1474. #else
  1475. REQUIRE(1);
  1476. LL32 (grHOSTDATA[0], *((USHORT*)pjGlyph)++);
  1477. #endif
  1478. }
  1479. else
  1480. {
  1481. //-----------------------------------------------------
  1482. // More than 16 pels in width
  1483. #if SWAT7
  1484. cw = (cxGlyph + 31) >> 5;
  1485. #else
  1486. lDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  1487. cw = (lDelta + 3) >> 2;
  1488. #endif
  1489. pTmp = pjGlyph + lDelta * pgb->sizlBitmap.cy;
  1490. for (;cyGlyph!=1; cyGlyph--)
  1491. {
  1492. WRITE_STRING(pjGlyph, cw);
  1493. pjGlyph += lDelta;
  1494. }
  1495. {
  1496. ULONG *pSrc = (ULONG*) pjGlyph + cw - 1;
  1497. WRITE_STRING(pjGlyph, cw - 1);
  1498. if ((BYTE *)pSrc+4<=pTmp)
  1499. {
  1500. REQUIRE(1);
  1501. LL32 (grHOSTDATA[0], *pSrc++ );
  1502. }
  1503. else
  1504. {
  1505. int Extra = (ULONG) pTmp - (ULONG) pSrc;
  1506. BYTE * pByte = (BYTE *)pSrc;
  1507. ULONG ulData;
  1508. DISPDBG((TEXT_DBG_LEVEL1,
  1509. "Caught it %s %d %d %x %x\n",
  1510. __FILE__, __LINE__, Extra, pTmp, pSrc));
  1511. if (Extra == 1)
  1512. ulData = (ULONG)(*pByte);
  1513. else if (Extra == 2)
  1514. ulData = (ULONG)(*(USHORT*)pByte);
  1515. else
  1516. ulData = (((ULONG)*(pByte+2) << 8) | (ULONG)*(pByte+1)) << 8 | *pByte;
  1517. REQUIRE(1);
  1518. LL32 (grHOSTDATA[0], ulData );
  1519. }
  1520. }
  1521. } // End more than 16 pels wide.
  1522. pgp++;
  1523. if (--cGlyph == 0) // We are done with this batch
  1524. break; // of glyphs. Break out of the glyph loop.
  1525. } // End Glyph Loop.
  1526. } // End Mono Spacing.
  1527. } // End if (cGlyph > 0)
  1528. //
  1529. // Done with this batch of Glyphs.
  1530. // Go get the next one.
  1531. //
  1532. } while (bMoreGlyphs);
  1533. } // End DC_TRIVIAL
  1534. else
  1535. {
  1536. // If there's clipping, call off to a function:
  1537. vMmClipGlyphExpansion(ppdev, pstro, pco);
  1538. }
  1539. ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
  1540. LL16(grCONTROL, ppdev->grCONTROL);
  1541. return(TRUE);
  1542. } // End DrvTextOut.
  1543. /******************************Public*Routine******************************\
  1544. * BOOL bEnableText
  1545. *
  1546. * Performs the necessary setup for the text drawing subcomponent.
  1547. *
  1548. \**************************************************************************/
  1549. BOOL bEnableText(
  1550. PDEV* ppdev)
  1551. {
  1552. // Our text algorithms require no initialization. If we were to
  1553. // do glyph caching, we would probably want to allocate off-screen
  1554. // memory and do a bunch of other stuff here.
  1555. DISPDBG((TEXT_DBG_LEVEL,"bEnableText: Entry.\n"));
  1556. #if RECORD_ON
  1557. LL( RECORD, 1); // Switch on
  1558. LL( RECORD, 2); // Pause
  1559. DISPDBG((TEXT_DBG_LEVEL1,"xbEnableText: Recording Paused.\n"));
  1560. #endif
  1561. return(TRUE);
  1562. }
  1563. /******************************Public*Routine******************************\
  1564. * VOID vDisableText
  1565. *
  1566. * Performs the necessary clean-up for the text drawing subcomponent.
  1567. *
  1568. \**************************************************************************/
  1569. VOID vDisableText(PDEV* ppdev)
  1570. {
  1571. // Here we free any stuff allocated in 'bEnableText'.
  1572. DISPDBG((TEXT_DBG_LEVEL,"vDisableText: Entry.\n"));
  1573. }
  1574. #if !SWAT3
  1575. #pragma optimize("", off) // Microsoft doesn't know how to do compile...
  1576. #endif
  1577. /******************************Public*Routine******************************\
  1578. * VOID vAssertModeText
  1579. *
  1580. * Disables or re-enables the text drawing subcomponent in preparation for
  1581. * full-screen entry/exit.
  1582. *
  1583. \**************************************************************************/
  1584. VOID vAssertModeText(
  1585. PDEV* ppdev,
  1586. BOOL bEnable)
  1587. {
  1588. #if SWAT3
  1589. SIZEL sizl;
  1590. POINTL pos;
  1591. int i;
  1592. if (bEnable)
  1593. {
  1594. // We are enabling the screen again, so allocate the font cache if it
  1595. // is not yet allocated.
  1596. if (ppdev->pofmFontCache == NULL)
  1597. {
  1598. #if MEMMGR
  1599. sizl.cx = ppdev->lDeltaScreen / FONTCELL_X;
  1600. #else
  1601. //sizl.cx = ppdev->cxMemory;
  1602. sizl.cx = ppdev->lDeltaScreen / ppdev->iBytesPerPixel / FONTCELL_X;
  1603. #endif
  1604. sizl.cy = (FONTCELL_COUNT + sizl.cx - 1) / sizl.cx;
  1605. sizl.cx *= FONTCELL_X;
  1606. sizl.cy *= FONTCELL_Y;
  1607. ppdev->pofmFontCache = AllocOffScnMem(ppdev, &sizl, 0, NULL);
  1608. //ppdev->pofmFontCache = AllocOffScnMem(ppdev, &sizl,
  1609. // PIXEL_AlIGN, NULL);
  1610. }
  1611. if (ppdev->pofmFontCache != NULL)
  1612. {
  1613. // Clear the entire font cell array.
  1614. pos.x = pos.y = 0;
  1615. for (i = 0; i < FONTCELL_COUNT; i++)
  1616. {
  1617. if (pos.y >= sizl.cy)
  1618. {
  1619. ppdev->fcGrid[i].x = 0;
  1620. ppdev->fcGrid[i].y = 0;
  1621. ppdev->fcGrid[i].pfc = (PFONTCACHE) -1;
  1622. }
  1623. else
  1624. {
  1625. ppdev->fcGrid[i].x = ppdev->pofmFontCache->x + pos.x;
  1626. ppdev->fcGrid[i].y = ppdev->pofmFontCache->y + pos.y;
  1627. ppdev->fcGrid[i].pfc = NULL;
  1628. ppdev->fcGrid[i].ulLastX = 0;
  1629. ppdev->fcGrid[i].pNext = NULL;
  1630. pos.x += FONTCELL_X;
  1631. if (pos.x >= (LONG) ppdev->cxMemory)
  1632. {
  1633. pos.x = 0;
  1634. pos.y += FONTCELL_Y;
  1635. }
  1636. }
  1637. }
  1638. }
  1639. }
  1640. else
  1641. {
  1642. // We are disabling the screen so destroy all cached fonts.
  1643. if (ppdev->pofmFontCache != NULL)
  1644. {
  1645. for (i = 0; i < FONTCELL_COUNT; i++)
  1646. {
  1647. if ( (ppdev->fcGrid[i].pfc != NULL)
  1648. && (ppdev->fcGrid[i].pfc != (PFONTCACHE) -1)
  1649. )
  1650. {
  1651. DrvDestroyFont(ppdev->fcGrid[i].pfc->pfo);
  1652. }
  1653. }
  1654. // Free the font cache cells.
  1655. FreeOffScnMem(ppdev, ppdev->pofmFontCache);
  1656. ppdev->pofmFontCache = NULL;
  1657. }
  1658. }
  1659. #elif !SWAT3
  1660. if (!bEnable)
  1661. {
  1662. // Remove all chained fonts.
  1663. PFONTCACHE p = ppdev->pfcChain;
  1664. while (p != NULL)
  1665. {
  1666. DrvDestroyFont(p->pfo);
  1667. p = ppdev->pfcChain;
  1668. }
  1669. }
  1670. #endif // SWAT3
  1671. }
  1672. #if !SWAT3
  1673. #pragma optimize("", on)
  1674. #endif
  1675. #if SWAT3
  1676. /******************************************************************************\
  1677. * PFONTCELL fcAllocCell(PFONTCACGE pfc)
  1678. *
  1679. * Allocate a font cell for the given font cache. Returns NULL if there are no
  1680. * more empty font cells.
  1681. \******************************************************************************/
  1682. PFONTCELL fcAllocCell(PFONTCACHE pfc)
  1683. {
  1684. int i;
  1685. PPDEV ppdev = pfc->ppdev;
  1686. PFONTCELL p = ppdev->fcGrid;
  1687. if (ppdev->pofmFontCache == NULL)
  1688. {
  1689. // Font cache is disabled, return NULL.
  1690. return NULL;
  1691. }
  1692. for (i = 0; i < FONTCELL_COUNT; i++, p++)
  1693. {
  1694. if (p->pfc == NULL)
  1695. {
  1696. p->pfc = pfc;
  1697. return p;
  1698. }
  1699. }
  1700. return NULL;
  1701. }
  1702. /******************************************************************************\
  1703. * void fcFreeCell(PFONTCELL pCell)
  1704. *
  1705. * Mark the given font cell as free.
  1706. \******************************************************************************/
  1707. void fcFreeCell(PFONTCELL pCell)
  1708. {
  1709. pCell->pfc = NULL;
  1710. pCell->ulLastX = 0;
  1711. pCell->pNext = NULL;
  1712. }
  1713. #endif // SWAT3
  1714. /******************************Public*Routine******************************\
  1715. * VOID DrvDestroyFont
  1716. *
  1717. * We're being notified that the given font is being deallocated; clean up
  1718. * anything we've stashed in the 'pvConsumer' field of the 'pfo'.
  1719. *
  1720. \**************************************************************************/
  1721. VOID DrvDestroyFont(FONTOBJ *pfo)
  1722. {
  1723. DISPDBG((TEXT_DBG_LEVEL, "DrvDestroyFont Entry\n"));
  1724. if (pfo->pvConsumer != NULL && pfo->pvConsumer != (PVOID) -1)
  1725. {
  1726. PFONTCACHE pfc = (PFONTCACHE) pfo->pvConsumer;
  1727. #if SWAT3
  1728. PFONTCELL pCell, pCellNext;
  1729. #else
  1730. PFONTMEMORY pfm, pfmNext;
  1731. #endif
  1732. PPDEV ppdev;
  1733. ppdev = pfc->ppdev;
  1734. LogFile((BUF, "DrvDestroyFont: "));
  1735. #if SWAT3
  1736. for (pCell = pfc->pFontCell; pCell != NULL; pCell = pCellNext)
  1737. {
  1738. pCellNext = pCell->pNext;
  1739. fcFreeCell(pCell);
  1740. }
  1741. LogFile((BUF, "\r\n"));
  1742. #else
  1743. for (pfm = pfc->pFontMemory; pfm != NULL; pfm = pfmNext)
  1744. {
  1745. pfmNext = pfm->pNext;
  1746. if (pfm->pTile != NULL)
  1747. {
  1748. FreeOffScnMem(pfc->ppdev, pfm->pTile);
  1749. }
  1750. MEMORY_FREE(pfm);
  1751. }
  1752. // Unhook the font cache from the chain.
  1753. if (pfc->pfcPrev != NULL)
  1754. {
  1755. pfc->pfcPrev->pfcNext = pfc->pfcNext;
  1756. }
  1757. else
  1758. {
  1759. ppdev->pfcChain = pfc->pfcNext;
  1760. }
  1761. if (pfc->pfcNext != NULL)
  1762. {
  1763. pfc->pfcNext->pfcPrev = pfc->pfcPrev;
  1764. }
  1765. #endif
  1766. LogFile((BUF, "\r\n"));
  1767. MEMORY_FREE(pfc);
  1768. }
  1769. pfo->pvConsumer = NULL;
  1770. DISPDBG((TEXT_DBG_LEVEL, "DrvDestroyFont Exit\n"));
  1771. }
  1772. /*
  1773. * GetGlyphSize
  1774. *
  1775. * Get the size (in pixels) of the requested glyph. Return the width of the
  1776. * glyph in bytes or 0 if the glyph is too big to cache.
  1777. *
  1778. */
  1779. long GetGlyphSize(
  1780. GLYPHBITS* pgb, // Pointer to glyph.
  1781. POINTL* pptlOrigin, // Pointer to return origin in.
  1782. DWORD* pcSize // Pointer to return size in.
  1783. )
  1784. {
  1785. long x, y, height = 0;
  1786. BYTE* pByte = pgb->aj;
  1787. int i;
  1788. x = (pgb->sizlBitmap.cx + 7) >> 3; // get width in bytes
  1789. if (x > 0)
  1790. {
  1791. // find first line in glyph that contains data
  1792. for (y = 0; y < pgb->sizlBitmap.cy; y++, pByte += x)
  1793. {
  1794. // walk trough every byte on a line
  1795. for (i = 0; i < x; i++)
  1796. {
  1797. if (pByte[i]) // we have data, so we are at the first line
  1798. {
  1799. // find the last line in te glyph that contains data
  1800. height = pgb->sizlBitmap.cy - y;
  1801. for (pByte += (height - 1) * x; height > 0; height--)
  1802. {
  1803. // walk trough every byte on a line
  1804. for (i = 0; i < x; i++)
  1805. {
  1806. if (pByte[i])
  1807. {
  1808. // test height of glyph
  1809. #if SWAT3
  1810. if (height > FONTCELL_Y)
  1811. #else
  1812. if (height > LINES_PER_TILE)
  1813. #endif
  1814. {
  1815. // glyph too big, mark it as uncacheable
  1816. *pcSize = (DWORD) -1;
  1817. return(0);
  1818. }
  1819. // fill return parameters
  1820. pptlOrigin->y = y;
  1821. *pcSize = PACK_XY(pgb->sizlBitmap.cx, height);
  1822. return(x);
  1823. }
  1824. }
  1825. pByte -= x;
  1826. }
  1827. }
  1828. }
  1829. }
  1830. }
  1831. // glyph is empty
  1832. *pcSize = 0;
  1833. return(0);
  1834. }
  1835. /*
  1836. * AllocFontCache
  1837. *
  1838. * Allocate the requsted memory in off-screen memory. Return TRUE and the x,y
  1839. * coordinates of the upper left corner of this region, or FALSE if there is
  1840. * not enough memory.
  1841. *
  1842. */
  1843. BOOL AllocFontCache(
  1844. PFONTCACHE pfc, // Pointer to font cache.
  1845. long cWidth, // Width (in bytes) to allocate.
  1846. long cHeight, // Height to allocate.
  1847. POINTL* ppnt // Point to return cooridinate in.
  1848. )
  1849. {
  1850. #if SWAT3
  1851. PFONTCELL pCell;
  1852. #else
  1853. SIZEL sizl;
  1854. PFONTMEMORY pfm;
  1855. #endif
  1856. long x;
  1857. PPDEV ppdev = pfc->ppdev;
  1858. #if !SWAT3
  1859. if (ppdev->iBytesPerPixel == 3)
  1860. {
  1861. sizl.cx = (128 + 2) / 3;
  1862. }
  1863. else
  1864. {
  1865. sizl.cx = 128 / ppdev->iBytesPerPixel;
  1866. }
  1867. sizl.cy = 16;
  1868. #endif
  1869. #if SWAT3
  1870. if (pfc->pFontCell == NULL)
  1871. {
  1872. pfc->pFontCell = fcAllocCell(pfc);
  1873. }
  1874. #else
  1875. if (pfc->pFontMemory == NULL)
  1876. {
  1877. pfc->pFontMemory = (PFONTMEMORY)
  1878. #ifdef WINNT_VER40
  1879. MEM_ALLOC(FL_ZERO_MEMORY, sizeof(FONTMEMORY), ALLOC_TAG);
  1880. #else
  1881. MEM_ALLOC(LMEM_FIXED | LMEM_ZEROINIT, sizeof(FONTMEMORY));
  1882. #endif
  1883. }
  1884. #endif
  1885. #if SWAT3
  1886. for (pCell = pfc->pFontCell; pCell != NULL; pCell = pCell->pNext)
  1887. {
  1888. x = pCell->ulLastX;
  1889. if (x + cWidth <= FONTCELL_X)
  1890. {
  1891. pCell->ulLastX += cWidth;
  1892. ppnt->x = pCell->x + x;
  1893. ppnt->y = pCell->y;
  1894. return TRUE;
  1895. }
  1896. if (pCell->pNext == NULL)
  1897. {
  1898. pCell->pNext = fcAllocCell(pfc);
  1899. }
  1900. }
  1901. #else
  1902. for (pfm = pfc->pFontMemory; pfm; pfm = pfm->pNext)
  1903. {
  1904. if (pfm->pTile == NULL)
  1905. {
  1906. #ifdef ALLOC_IN_CREATESURFACE
  1907. if (!ppdev->bDirectDrawInUse)
  1908. #endif
  1909. pfm->pTile = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
  1910. if (pfm->pTile == NULL)
  1911. {
  1912. return FALSE;
  1913. }
  1914. ppnt->x = pfm->pTile->x;
  1915. ppnt->y = pfm->pTile->y;
  1916. pfm->ulLastX = cWidth;
  1917. return TRUE;
  1918. }
  1919. x = pfm->ulLastX;
  1920. if (x + cWidth <= BYTES_PER_TILE)
  1921. {
  1922. pfm->ulLastX += cWidth;
  1923. ppnt->x = pfm->pTile->x + x;
  1924. ppnt->y = pfm->pTile->y;
  1925. return TRUE;
  1926. }
  1927. if (pfm->pNext == NULL)
  1928. {
  1929. pfm->pNext = (PFONTMEMORY)
  1930. #ifdef WINNT_VER40
  1931. MEM_ALLOC(FL_ZERO_MEMORY, sizeof(FONTMEMORY), ALLOC_TAG);
  1932. #else
  1933. MEM_ALLOC(LMEM_FIXED | LMEM_ZEROINIT, sizeof(FONTMEMORY));
  1934. #endif
  1935. }
  1936. }
  1937. #endif
  1938. return FALSE;
  1939. }
  1940. /*
  1941. * AllocGlyph
  1942. *
  1943. * Allocate memory for the requested glyph and copy the glyph into off-screen
  1944. * memory. If there is not enough off-screen memory left, or the glyph is too
  1945. * large to glyph, return FALSE, otherwise return TRUE.
  1946. *
  1947. */
  1948. VOID AllocGlyph(
  1949. PFONTCACHE pfc, // pointer to font cache
  1950. GLYPHBITS* pgb, // pointer to glyph to cache
  1951. GLYPHCACHE* pgc // pointer to glyph cache structure
  1952. )
  1953. {
  1954. long cBytes;
  1955. BYTE *pOffScreen, *pSrc;
  1956. long y;
  1957. PDEV *ppdev;
  1958. POINTL pointl;
  1959. ppdev = pfc->ppdev;
  1960. cBytes = GetGlyphSize(pgb, &pgc->ptlOrigin, &pgc->cSize);
  1961. if (cBytes == 0)
  1962. {
  1963. pgc->xyPos = (DWORD) -1;
  1964. LogFile((BUF, "GC:F\r\n"));
  1965. return;
  1966. }
  1967. if (AllocFontCache(pfc, cBytes, pgc->cSize >> 16, &pointl) == FALSE)
  1968. {
  1969. pgc->cSize = (DWORD) -1;
  1970. LogFile((BUF, "GC:F\r\n"));
  1971. return;
  1972. }
  1973. pOffScreen = ppdev->pjScreen + pointl.x + pointl.y * ppdev->lDeltaScreen;
  1974. pSrc = &pgb->aj[pgc->ptlOrigin.y * cBytes];
  1975. y = (long) (pgc->cSize >> 16);
  1976. if (cBytes == sizeof(BYTE))
  1977. {
  1978. while (y-- > 0)
  1979. {
  1980. *pOffScreen = Swiz[*pSrc];
  1981. pOffScreen += ppdev->lDeltaScreen;
  1982. pSrc += sizeof(BYTE);
  1983. }
  1984. }
  1985. else
  1986. {
  1987. while (y-- > 0)
  1988. {
  1989. long lDelta = ppdev->lDeltaScreen - cBytes;
  1990. long i;
  1991. for (i = cBytes; i > 0; i--)
  1992. {
  1993. *pOffScreen++ = Swiz[*pSrc++];
  1994. }
  1995. pOffScreen += lDelta;
  1996. }
  1997. }
  1998. pgc->xyPos = PACK_XY(pointl.x * 8, pointl.y);
  1999. pgc->ptlOrigin.x = pgb->ptlOrigin.x;
  2000. pgc->ptlOrigin.y += pgb->ptlOrigin.y;
  2001. LogFile((BUF, "GC:S\r\n"));
  2002. }
  2003. #if !(USE_ASM && defined(i386))
  2004. /*
  2005. * FontCache
  2006. *
  2007. * Draw glyphs using the off-screen font cache.
  2008. *
  2009. */
  2010. VOID FontCache(
  2011. PFONTCACHE pfc, // Pointer to font cache.
  2012. STROBJ* pstro // Pointer to glyphs.
  2013. )
  2014. {
  2015. PDEV* ppdev;
  2016. BOOL bMoreGlyphs = TRUE;
  2017. ULONG cGlyph;
  2018. GLYPHPOS* pgp;
  2019. POINTL ptlOrigin;
  2020. PGLYPHCACHE pgc;
  2021. ULONG ulCharInc;
  2022. // set pointer to physical device
  2023. ppdev = pfc->ppdev;
  2024. // loop until there are no more glyphs to process
  2025. while (bMoreGlyphs)
  2026. {
  2027. if (pstro->pgp != NULL)
  2028. {
  2029. // we have just one set of glyphs
  2030. pgp = pstro->pgp;
  2031. cGlyph = pstro->cGlyphs;
  2032. bMoreGlyphs = FALSE;
  2033. }
  2034. else
  2035. {
  2036. // enumerate a set of glyphs
  2037. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  2038. }
  2039. if (pstro->ulCharInc)
  2040. {
  2041. // fixed fonts... get x and y coordinates of first glyph
  2042. ptlOrigin.x = pgp->ptl.x;
  2043. ptlOrigin.y = pgp->ptl.y;
  2044. // get glyph increment
  2045. ulCharInc = pstro->ulCharInc;
  2046. // walk through all glyphs
  2047. while (cGlyph-- > 0)
  2048. {
  2049. if (pgp->hg < MAX_GLYPHS)
  2050. {
  2051. // this glyph index is cacheable
  2052. pgc = &pfc->aGlyphs[pgp->hg];
  2053. if (pgc->xyPos == 0)
  2054. {
  2055. // cache the glyph
  2056. AllocGlyph(pfc, pgp->pgdf->pgb, pgc);
  2057. }
  2058. if ((long) pgc->cSize > 0)
  2059. {
  2060. LogFile((BUF, "GC:H\r\n"));
  2061. // the glyph is cached, blit it on the screen
  2062. REQUIRE(7);
  2063. LL_OP0(ptlOrigin.x + pgc->ptlOrigin.x + ppdev->ptlOffset.x,
  2064. ptlOrigin.y + pgc->ptlOrigin.y + ppdev->ptlOffset.y);
  2065. LL32 (grOP2_opMRDRAM, pgc->xyPos);
  2066. LL32 (grBLTEXT_EX.dw, pgc->cSize);
  2067. }
  2068. else if ((long) pgc->cSize == -1)
  2069. {
  2070. // the glyph is uncacheable, draw it directly
  2071. DrawGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin);
  2072. }
  2073. }
  2074. else
  2075. {
  2076. // the glyph index is out of range, draw it directly
  2077. DrawGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin);
  2078. }
  2079. // increment glyph x coordinate
  2080. ptlOrigin.x += ulCharInc;
  2081. // next glyph
  2082. pgp++;
  2083. }
  2084. }
  2085. else
  2086. {
  2087. // variable width fonts, walk trough all glyphs
  2088. while (cGlyph-- > 0)
  2089. {
  2090. if (pgp->hg < MAX_GLYPHS)
  2091. {
  2092. // this glyph index is cacheable
  2093. pgc = &pfc->aGlyphs[pgp->hg];
  2094. if (pgc->xyPos == 0)
  2095. {
  2096. // cache the glyph
  2097. AllocGlyph(pfc, pgp->pgdf->pgb, pgc);
  2098. }
  2099. if ((long) pgc->cSize > 0)
  2100. {
  2101. LogFile((BUF, "GC:H\r\n"));
  2102. // the glyph is cached, blit it on the screen
  2103. REQUIRE(7);
  2104. LL_OP0(pgp->ptl.x + pgc->ptlOrigin.x + ppdev->ptlOffset.x,
  2105. pgp->ptl.y + pgc->ptlOrigin.y + ppdev->ptlOffset.y);
  2106. LL32 (grOP2_opMRDRAM, pgc->xyPos);
  2107. LL32 (grBLTEXT_EX.dw, pgc->cSize);
  2108. }
  2109. else if ((long) pgc->cSize == -1)
  2110. {
  2111. // the glyph is uncacheable, draw it directly
  2112. DrawGlyph(ppdev, pgp->pgdf->pgb, pgp->ptl);
  2113. }
  2114. }
  2115. else
  2116. {
  2117. // the glyph index is out of range, draw it directly
  2118. DrawGlyph(ppdev, pgp->pgdf->pgb, pgp->ptl);
  2119. }
  2120. // next glyph
  2121. pgp++;
  2122. }
  2123. }
  2124. }
  2125. }
  2126. /*
  2127. * DrawGlyph
  2128. *
  2129. * Draw glyphs directly on the screen.
  2130. *
  2131. */
  2132. VOID DrawGlyph(
  2133. PDEV* ppdev, // Pointer to physical device.
  2134. GLYPHBITS* pgb, // Pointer to glyph to draw.
  2135. POINTL ptl // Location of glyph.
  2136. )
  2137. {
  2138. BYTE* pjGlyph;
  2139. ULONG cyGlyph;
  2140. #if SWAT7
  2141. ULONG cxGlyph;
  2142. ULONG xOrigin;
  2143. LONG lDelta;
  2144. #endif
  2145. LogFile((BUF, "GC:M\r\n"));
  2146. #if SWAT7
  2147. xOrigin = ptl.x + pgb->ptlOrigin.x;
  2148. cxGlyph = pgb->sizlBitmap.cx;
  2149. cyGlyph = pgb->sizlBitmap.cy;
  2150. pjGlyph = pgb->aj;
  2151. lDelta = (cxGlyph + 7) >> 3;
  2152. #endif
  2153. // start the blit
  2154. REQUIRE(4);
  2155. LL_DRAWBLTDEF(TEXT_EXPAND_XPAR, 0);
  2156. LL_OP2_MONO(0, 0);
  2157. #if !SWAT7
  2158. REQUIRE(5);
  2159. LL_OP0(ptl.x + pgb->ptlOrigin.x + ppdev->ptlOffset.x,
  2160. ptl.y + pgb->ptlOrigin.y + ppdev->ptlOffset.y);
  2161. LL_BLTEXT(pgb->sizlBitmap.cx, pgb->sizlBitmap.cy);
  2162. pjGlyph = pgb->aj;
  2163. cyGlyph = pgb->sizlBitmap.cy;
  2164. #endif
  2165. #if SWAT7
  2166. //
  2167. // Test for 5465AD hardware bug in 8-bpp.
  2168. //
  2169. if ( (cxGlyph > 64) && (cxGlyph < 128)
  2170. && (ppdev->iBytesPerPixel == 1)
  2171. )
  2172. {
  2173. Xfer64Pixels(ppdev, xOrigin, ptl.y + pgb->ptlOrigin.y, 0, cyGlyph,
  2174. pjGlyph, cxGlyph);
  2175. pjGlyph += 64 / 8;
  2176. xOrigin += 64;
  2177. cxGlyph -= 64;
  2178. }
  2179. REQUIRE(5);
  2180. LL_OP0(xOrigin + ppdev->ptlOffset.x,
  2181. ptl.y + pgb->ptlOrigin.y + ppdev->ptlOffset.y);
  2182. LL_BLTEXT(cxGlyph, cyGlyph);
  2183. #endif
  2184. #if SWAT7
  2185. if (cxGlyph <= 8)
  2186. #else
  2187. if (pgb->sizlBitmap.cx <= 8)
  2188. #endif
  2189. {
  2190. // just one byte per line
  2191. while (cyGlyph--)
  2192. {
  2193. REQUIRE(1);
  2194. LL32 (grHOSTDATA[0], *pjGlyph);
  2195. #if SWAT7
  2196. pjGlyph += lDelta;
  2197. #else
  2198. pjGlyph++;
  2199. #endif
  2200. }
  2201. }
  2202. #if SWAT7
  2203. else if (cxGlyph <= 16)
  2204. #else
  2205. else if (pgb->sizlBitmap.cx <= 16)
  2206. #endif
  2207. {
  2208. // just two bytes per line
  2209. while (cyGlyph--)
  2210. {
  2211. REQUIRE(1);
  2212. LL32 (grHOSTDATA[0], *(WORD *) pjGlyph);
  2213. #if SWAT7
  2214. pjGlyph += lDelta;
  2215. #else
  2216. pjGlyph += 2;
  2217. #endif
  2218. }
  2219. }
  2220. #if SWAT7
  2221. else if (cxGlyph <= 24)
  2222. #else
  2223. else if (pgb->sizlBitmap.cx <= 24)
  2224. #endif
  2225. {
  2226. // just three bytes per line
  2227. while (cyGlyph--)
  2228. {
  2229. REQUIRE(1);
  2230. LL32 (grHOSTDATA[0], *(DWORD *) pjGlyph);
  2231. #if SWAT7
  2232. pjGlyph += lDelta;
  2233. #else
  2234. pjGlyph += 3;
  2235. #endif
  2236. }
  2237. }
  2238. #if SWAT7
  2239. else if (cxGlyph <= 32)
  2240. #else
  2241. else if (pgb->sizlBitmap.cx <= 32)
  2242. #endif
  2243. {
  2244. // just four bytes per line
  2245. while (cyGlyph--)
  2246. {
  2247. REQUIRE(1);
  2248. LL32 (grHOSTDATA[0], *(DWORD *) pjGlyph);
  2249. #if SWAT7
  2250. pjGlyph += lDelta;
  2251. #else
  2252. pjGlyph += 4;
  2253. #endif
  2254. }
  2255. }
  2256. else
  2257. {
  2258. // any number of bytes per line
  2259. #if SWAT7
  2260. int cw = (cxGlyph + 31) >> 5;
  2261. #else
  2262. long lDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  2263. int cw = (lDelta + 3) >> 2;
  2264. #endif
  2265. BYTE * pTmp = pjGlyph + lDelta * pgb->sizlBitmap.cy;
  2266. for (;cyGlyph!=1; cyGlyph--)
  2267. {
  2268. WRITE_STRING(pjGlyph, cw);
  2269. pjGlyph += lDelta;
  2270. }
  2271. {
  2272. ULONG *pSrc = (ULONG*) pjGlyph + cw - 1;
  2273. WRITE_STRING(pjGlyph, cw - 1);
  2274. if ((BYTE *)pSrc+4<=pTmp)
  2275. {
  2276. REQUIRE(1);
  2277. LL32 (grHOSTDATA[0], *pSrc++ );
  2278. }
  2279. else
  2280. {
  2281. int Extra = (ULONG) pTmp - (ULONG) pSrc;
  2282. BYTE * pByte = (BYTE *)pSrc;
  2283. ULONG ulData;
  2284. DISPDBG((TEXT_DBG_LEVEL1,
  2285. "Caught it %s %d %d %x %x\n",
  2286. __FILE__, __LINE__, Extra, pTmp, pSrc));
  2287. if (Extra == 1)
  2288. ulData = (ULONG)(*pByte);
  2289. else if (Extra == 2)
  2290. ulData = (ULONG)(*(USHORT*)pByte);
  2291. else
  2292. ulData = (((ULONG)*(pByte+2) << 8) | (ULONG)*(pByte+1)) << 8 | *pByte;
  2293. REQUIRE(1);
  2294. LL32 (grHOSTDATA[0], ulData );
  2295. }
  2296. }
  2297. }
  2298. // reset to transparent cache expansion
  2299. LL_DRAWBLTDEF(CACHE_EXPAND_XPAR, 2);
  2300. }
  2301. VOID ClipCache(
  2302. PFONTCACHE pfc, // Pointer to font cache.
  2303. STROBJ* pstro, // Pointer to glyphs.
  2304. RECTL rclBounds // Clipping rectangle.
  2305. )
  2306. {
  2307. PDEV* ppdev;
  2308. BOOL bMoreGlyphs = TRUE;
  2309. ULONG cGlyph;
  2310. GLYPHPOS* pgp;
  2311. POINTL ptlOrigin;
  2312. PGLYPHCACHE pgc;
  2313. ULONG ulCharInc;
  2314. // set pointer to physical device
  2315. ppdev = pfc->ppdev;
  2316. // loop until there are no more glyphs to process
  2317. while (bMoreGlyphs)
  2318. {
  2319. if (pstro->pgp != NULL)
  2320. {
  2321. // we have just one set of glyphs
  2322. pgp = pstro->pgp;
  2323. cGlyph = pstro->cGlyphs;
  2324. bMoreGlyphs = FALSE;
  2325. }
  2326. else
  2327. {
  2328. // enumerate a set of glyphs
  2329. bMoreGlyphs = STROBJ_bEnum(pstro, &cGlyph, &pgp);
  2330. }
  2331. // get x and y coordinates of first glyph
  2332. ptlOrigin.x = pgp->ptl.x;
  2333. ptlOrigin.y = pgp->ptl.y;
  2334. // get glyph increment
  2335. ulCharInc = pstro->ulCharInc;
  2336. // walk through all glyphs
  2337. while (cGlyph-- > 0)
  2338. {
  2339. if (pgp->hg < MAX_GLYPHS)
  2340. {
  2341. // this glyph index is cacheable
  2342. pgc = &pfc->aGlyphs[pgp->hg];
  2343. if (pgc->xyPos == 0)
  2344. {
  2345. // cache the glyph
  2346. AllocGlyph(pfc, pgp->pgdf->pgb, pgc);
  2347. }
  2348. if ((long) pgc->cSize > 0)
  2349. {
  2350. RECTL rcl;
  2351. LONG i, cx, cy;
  2352. ULONG xyPos;
  2353. // the glyph is cached, ckeck clipping
  2354. rcl.left = ptlOrigin.x + pgc->ptlOrigin.x;
  2355. rcl.top = ptlOrigin.y + pgc->ptlOrigin.y;
  2356. rcl.right = rcl.left + (pgc->cSize & 0x0000FFFF);
  2357. rcl.bottom = rcl.top + (pgc->cSize >> 16);
  2358. xyPos = pgc->xyPos;
  2359. i = rclBounds.left - rcl.left;
  2360. if (i > 0)
  2361. {
  2362. // the glyph is partially clipped on the left, draw it
  2363. // directly
  2364. ClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds);
  2365. }
  2366. else
  2367. {
  2368. LogFile((BUF, "GC:H\r\n"));
  2369. cx = min(rcl.right, rclBounds.right) - rcl.left;
  2370. if (cx > 0)
  2371. {
  2372. i = rclBounds.top - rcl.top;
  2373. if (i > 0)
  2374. {
  2375. rcl.top += i;
  2376. xyPos += i << 16;
  2377. }
  2378. cy = min(rcl.bottom, rclBounds.bottom) - rcl.top;
  2379. if (cy > 0)
  2380. {
  2381. REQUIRE(7);
  2382. LL_OP0(rcl.left + ppdev->ptlOffset.x,
  2383. rcl.top + ppdev->ptlOffset.y);
  2384. LL32(grOP2_opMRDRAM, xyPos);
  2385. LL_BLTEXT(cx, cy);
  2386. }
  2387. }
  2388. }
  2389. }
  2390. else if ((long) pgc->cSize == -1)
  2391. {
  2392. // the glyph is uncacheable, draw it directly
  2393. ClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds);
  2394. }
  2395. }
  2396. else
  2397. {
  2398. // the glyph index is out of range, draw it directly
  2399. ClipGlyph(ppdev, pgp->pgdf->pgb, ptlOrigin, rclBounds);
  2400. }
  2401. // next glyph
  2402. pgp++;
  2403. if (ulCharInc == 0)
  2404. {
  2405. ptlOrigin.x = pgp->ptl.x;
  2406. ptlOrigin.y = pgp->ptl.y;
  2407. }
  2408. else
  2409. {
  2410. // increment glyph x coordinate
  2411. ptlOrigin.x += ulCharInc;
  2412. }
  2413. }
  2414. }
  2415. }
  2416. VOID ClipGlyph(
  2417. PDEV* ppdev, // Pointer to physical device.
  2418. GLYPHBITS* pgb, // Pointer to glyph to draw.
  2419. POINTL ptl, // Location of glyph.
  2420. RECTL rclBounds // Clipping rectangle.
  2421. )
  2422. {
  2423. BYTE* pjGlyph;
  2424. LONG cx, cy, lDelta, i;
  2425. RECTL rcl;
  2426. ULONG xBit;
  2427. LogFile((BUF, "GC:M\r\n"));
  2428. rcl.left = ptl.x + pgb->ptlOrigin.x;
  2429. rcl.top = ptl.y + pgb->ptlOrigin.y;
  2430. rcl.right = rcl.left + pgb->sizlBitmap.cx;
  2431. rcl.bottom = rcl.top + pgb->sizlBitmap.cy;
  2432. xBit = 0;
  2433. pjGlyph = pgb->aj;
  2434. lDelta = (pgb->sizlBitmap.cx + 7) >> 3;
  2435. i = rclBounds.left - rcl.left;
  2436. if (i > 0)
  2437. {
  2438. pjGlyph += i >> 3;
  2439. xBit = i & 7;
  2440. rcl.left += i;
  2441. }
  2442. cx = min(rcl.right, rclBounds.right) - rcl.left;
  2443. if (cx > 0)
  2444. {
  2445. i = rclBounds.top - rcl.top;
  2446. if (i > 0)
  2447. {
  2448. pjGlyph += i * lDelta;
  2449. rcl.top += i;
  2450. }
  2451. cy = min(rcl.bottom, rclBounds.bottom) - rcl.top;
  2452. if (cy > 0)
  2453. {
  2454. // start the blit
  2455. REQUIRE(4);
  2456. LL_DRAWBLTDEF(TEXT_EXPAND_XPAR, 0);
  2457. LL_OP2(xBit, 0);
  2458. #if SWAT7
  2459. //
  2460. // Test for 5465AD hardware bug in 8-bpp.
  2461. //
  2462. if ((cx > 64) && (cx < 128) && (ppdev->iBytesPerPixel == 1))
  2463. {
  2464. Xfer64Pixels(ppdev, rcl.left, rcl.top, xBit, cy, pjGlyph,
  2465. pgb->sizlBitmap.cx);
  2466. pjGlyph += 64 / 8;
  2467. rcl.left += 64;
  2468. cx -= 64;
  2469. }
  2470. #endif
  2471. REQUIRE(5);
  2472. LL_OP0(rcl.left + ppdev->ptlOffset.x,
  2473. rcl.top + ppdev->ptlOffset.y);
  2474. LL_BLTEXT(cx, cy);
  2475. cx = (xBit + cx + 7) >> 3;
  2476. switch (cx)
  2477. {
  2478. case 1:
  2479. while (cy--)
  2480. {
  2481. REQUIRE(1);
  2482. LL32(grHOSTDATA[0], *(BYTE *) pjGlyph);
  2483. pjGlyph += lDelta;
  2484. }
  2485. break;
  2486. case 2:
  2487. while (cy--)
  2488. {
  2489. REQUIRE(1);
  2490. LL32(grHOSTDATA[0], *(WORD *) pjGlyph);
  2491. pjGlyph += lDelta;
  2492. }
  2493. break;
  2494. case 3:
  2495. case 4:
  2496. while (cy--)
  2497. {
  2498. REQUIRE(1);
  2499. LL32(grHOSTDATA[0], *(DWORD *) pjGlyph);
  2500. pjGlyph += lDelta;
  2501. }
  2502. break;
  2503. default:
  2504. while (cy--)
  2505. {
  2506. WRITE_STRING(pjGlyph, (cx + 3) / 4);
  2507. pjGlyph += lDelta;
  2508. }
  2509. break;
  2510. }
  2511. // reset to transparent cache expansion
  2512. REQUIRE(2);
  2513. LL_DRAWBLTDEF(CACHE_EXPAND_XPAR, 2);
  2514. }
  2515. }
  2516. }
  2517. #endif // !(USE_ASM && defined(i386))