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.

2018 lines
50 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name
  4. trimesh.cxx
  5. Abstract:
  6. Implement triangle mesh API
  7. Author:
  8. Mark Enstrom (marke) 23-Jun-1996
  9. Enviornment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #include "dciman.h"
  15. #pragma hdrstop
  16. extern PFNGRFILL gpfnGradientFill;
  17. #if !(_WIN32_WINNT >= 0x500)
  18. /**************************************************************************\
  19. * gulDither32 - 4-4 dither matrix
  20. *
  21. *
  22. * History:
  23. *
  24. * 1/31/1997 Mark Enstrom [marke]
  25. *
  26. \**************************************************************************/
  27. ULONG gulDither32[] =
  28. {
  29. 0x00000000,
  30. 0x00008000,
  31. 0x00002000,
  32. 0x0000a000,
  33. 0x0000c000,
  34. 0x00004000,
  35. 0x0000e000,
  36. 0x00006000,
  37. 0x00003000,
  38. 0x0000b000,
  39. 0x00001000,
  40. 0x00009000,
  41. 0x0000f000,
  42. 0x00007000,
  43. 0x0000d000,
  44. 0x00005000
  45. };
  46. /******************************Public*Routine******************************\
  47. * vFillTriDIBUnreadable
  48. *
  49. * If a surface can't be read, draw triangle to a scan line, then call
  50. * SetDIBitsToDevice on each scan line
  51. *
  52. * Arguments:
  53. *
  54. *
  55. *
  56. * Return Value:
  57. *
  58. *
  59. *
  60. * History:
  61. *
  62. * 11/21/1996 Mark Enstrom [marke]
  63. *
  64. \**************************************************************************/
  65. VOID
  66. vFillTriDIBUnreadable(
  67. PDIBINFO pDibInfo,
  68. PTRIANGLEDATA ptData
  69. )
  70. {
  71. LONG lDelta = pDibInfo->stride;
  72. LONG yScan = ptData->y0;
  73. LONG yScanBottom;
  74. LONG cxClip = ptData->rcl.right - ptData->rcl.left;
  75. PTRIEDGE pEdge = &ptData->TriEdge[0];
  76. LONG dRed = ptData->dRdX;
  77. LONG dGreen = ptData->dGdX;
  78. LONG dBlue = ptData->dBdX;
  79. LONG dAlpha = ptData->dAdX;
  80. ULONG Red;
  81. ULONG Green;
  82. ULONG Blue;
  83. ULONG Alpha;
  84. BITMAPINFO bmi;
  85. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  86. bmi.bmiHeader.biWidth = cxClip;
  87. bmi.bmiHeader.biHeight = 1;
  88. bmi.bmiHeader.biPlanes = 1;
  89. bmi.bmiHeader.biBitCount = 32;
  90. bmi.bmiHeader.biCompression = BI_RGB;
  91. bmi.bmiHeader.biSizeImage = 0;
  92. bmi.bmiHeader.biXPelsPerMeter = 0;
  93. bmi.bmiHeader.biYPelsPerMeter = 0;
  94. bmi.bmiHeader.biClrUsed = 0;
  95. bmi.bmiHeader.biClrImportant = 0;
  96. PBYTE pDst = (PBYTE)LOCALALLOC(4 * cxClip);
  97. if (pDst == NULL)
  98. {
  99. return;
  100. }
  101. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  102. while(yScan < yScanBottom)
  103. {
  104. PULONG pulDstX;
  105. PULONG pulDstScanRight,pulDstScanLeft;
  106. LONG xScanRight;
  107. LONG xScanLeft;
  108. Red = pEdge->Red;
  109. Green = pEdge->Green;
  110. Blue = pEdge->Blue;
  111. Alpha = pEdge->Alpha;
  112. xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  113. xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  114. if (xScanLeft < xScanRight)
  115. {
  116. pulDstX = (PULONG)pDst + xScanLeft - ptData->rcl.left;
  117. pulDstScanRight = (PULONG)pDst + xScanRight - ptData->rcl.left;
  118. //
  119. // skip span from left edge scan to left edge clip rect
  120. //
  121. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  122. if (GradientLeft > 0)
  123. {
  124. Red += dRed * GradientLeft;
  125. Green += dGreen * GradientLeft;
  126. Blue += dBlue * GradientLeft;
  127. Alpha += dAlpha * GradientLeft;
  128. }
  129. //
  130. // fill span within clipping boundary
  131. //
  132. while (pulDstX < pulDstScanRight)
  133. {
  134. *pulDstX = ((Alpha & 0x00ff0000) << 8) |
  135. ((Red & 0x00ff0000) ) |
  136. ((Green & 0x00ff0000) >> 8) |
  137. ((Blue & 0x00ff0000) >> 16);
  138. pulDstX++;
  139. Red += dRed;
  140. Green += dGreen;
  141. Blue += dBlue;
  142. Alpha += dAlpha;
  143. }
  144. //
  145. // write span to device
  146. //
  147. SetDIBitsToDevice(pDibInfo->hdc,
  148. xScanLeft,
  149. yScan,
  150. xScanRight-xScanLeft,
  151. 1,
  152. xScanLeft-ptData->rcl.left,
  153. 0,
  154. 0,
  155. 1,
  156. pDst,
  157. &bmi,
  158. DIB_RGB_COLORS
  159. );
  160. }
  161. pEdge++;
  162. yScan++;
  163. }
  164. }
  165. /******************************Public*Routine******************************\
  166. * vFillTriDIB32BGRA
  167. *
  168. *
  169. * Arguments:
  170. *
  171. *
  172. *
  173. * Return Value:
  174. *
  175. *
  176. *
  177. * History:
  178. *
  179. * 11/21/1996 Mark Enstrom [marke]
  180. *
  181. \**************************************************************************/
  182. VOID
  183. vFillTriDIB32BGRA(
  184. PDIBINFO pDibInfo,
  185. PTRIANGLEDATA ptData
  186. )
  187. {
  188. LONG lDelta = pDibInfo->stride;
  189. LONG yScan = ptData->y0;
  190. LONG yScanBottom;
  191. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  192. PTRIEDGE pEdge = &ptData->TriEdge[0];
  193. LONG dRed = ptData->dRdX;
  194. LONG dGreen = ptData->dGdX;
  195. LONG dBlue = ptData->dBdX;
  196. LONG dAlpha = ptData->dAdX;
  197. ULONG Red;
  198. ULONG Green;
  199. ULONG Blue;
  200. ULONG Alpha;
  201. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  202. while(yScan < yScanBottom)
  203. {
  204. PULONG pulDstX;
  205. PULONG pulDstScanRight,pulDstScanLeft;
  206. Red = pEdge->Red;
  207. Green = pEdge->Green;
  208. Blue = pEdge->Blue;
  209. Alpha = pEdge->Alpha;
  210. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  211. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  212. if (xScanLeft < xScanRight)
  213. {
  214. pulDstX = (PULONG)pDst + xScanLeft;
  215. pulDstScanRight = (PULONG)pDst + xScanRight;
  216. //
  217. // skip pixels from left edge to left clip, while
  218. // incrementing gradient
  219. //
  220. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  221. if (GradientLeft > 0)
  222. {
  223. Red += dRed * GradientLeft;
  224. Green += dGreen * GradientLeft;
  225. Blue += dBlue * GradientLeft;
  226. Alpha += dAlpha * GradientLeft;
  227. }
  228. //
  229. // fill span
  230. //
  231. while (pulDstX < pulDstScanRight)
  232. {
  233. *pulDstX = ((Alpha & 0x00ff0000) << 8) |
  234. ((Red & 0x00ff0000) ) |
  235. ((Green & 0x00ff0000) >> 8) |
  236. ((Blue & 0x00ff0000) >> 16);
  237. pulDstX++;
  238. Red += dRed;
  239. Green += dGreen;
  240. Blue += dBlue;
  241. Alpha += dAlpha;
  242. }
  243. }
  244. pDst += lDelta;
  245. pEdge++;
  246. yScan++;
  247. }
  248. }
  249. /******************************Public*Routine******************************\
  250. * vFillTriDIB32RGB
  251. *
  252. *
  253. * Arguments:
  254. *
  255. *
  256. *
  257. * Return Value:
  258. *
  259. *
  260. *
  261. * History:
  262. *
  263. * 11/21/1996 Mark Enstrom [marke]
  264. *
  265. \**************************************************************************/
  266. VOID
  267. vFillTriDIB32RGB(
  268. PDIBINFO pDibInfo,
  269. PTRIANGLEDATA ptData
  270. )
  271. {
  272. LONG lDelta = pDibInfo->stride;
  273. LONG yScan = ptData->y0;
  274. LONG yScanBottom;
  275. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  276. PTRIEDGE pEdge = &ptData->TriEdge[0];
  277. LONG dRed = ptData->dRdX;
  278. LONG dGreen = ptData->dGdX;
  279. LONG dBlue = ptData->dBdX;
  280. ULONG Red;
  281. ULONG Green;
  282. ULONG Blue;
  283. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  284. while(yScan < yScanBottom)
  285. {
  286. PULONG pulDstX;
  287. PULONG pulDstScanRight,pulDstScanLeft;
  288. Red = pEdge->Red;
  289. Green = pEdge->Green;
  290. Blue = pEdge->Blue;
  291. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  292. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  293. if (xScanLeft < xScanRight)
  294. {
  295. pulDstX = (PULONG)pDst + xScanLeft;
  296. pulDstScanRight = (PULONG)pDst + xScanRight;
  297. //
  298. // skip pixels from left edge to left clip, while
  299. // incrementing gradient
  300. //
  301. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  302. if (GradientLeft > 0)
  303. {
  304. Red += dRed * GradientLeft;
  305. Green += dGreen * GradientLeft;
  306. Blue += dBlue * GradientLeft;
  307. }
  308. //
  309. // fill scan
  310. //
  311. while (pulDstX < pulDstScanRight)
  312. {
  313. *pulDstX = ((Red & 0x00ff0000)) |
  314. ((Green & 0x00ff0000) >> 8) |
  315. ((Blue & 0x00ff0000) >> 16);
  316. pulDstX++;
  317. Red += dRed;
  318. Green += dGreen;
  319. Blue += dBlue;
  320. }
  321. }
  322. pDst += lDelta;
  323. pEdge++;
  324. yScan++;
  325. }
  326. }
  327. /******************************Public*Routine******************************\
  328. * vFillTriDIB24RGB
  329. *
  330. *
  331. * Arguments:
  332. *
  333. *
  334. *
  335. * Return Value:
  336. *
  337. *
  338. *
  339. * History:
  340. *
  341. * 11/21/1996 Mark Enstrom [marke]
  342. *
  343. \**************************************************************************/
  344. VOID
  345. vFillTriDIB24RGB(
  346. PDIBINFO pDibInfo,
  347. PTRIANGLEDATA ptData
  348. )
  349. {
  350. LONG lDelta = pDibInfo->stride;
  351. LONG yScan = ptData->y0;
  352. LONG yScanBottom;
  353. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  354. PTRIEDGE pEdge = &ptData->TriEdge[0];
  355. LONG dRed = ptData->dRdX;
  356. LONG dGreen = ptData->dGdX;
  357. LONG dBlue = ptData->dBdX;
  358. ULONG Red;
  359. ULONG Green;
  360. ULONG Blue;
  361. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  362. while(yScan < yScanBottom)
  363. {
  364. PBYTE pDstX;
  365. PBYTE pDstScanRight;
  366. Red = pEdge->Red;
  367. Green = pEdge->Green;
  368. Blue = pEdge->Blue;
  369. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  370. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  371. if (xScanLeft < xScanRight)
  372. {
  373. pDstX = pDst + 3 * xScanLeft;
  374. pDstScanRight = pDst + 3 * xScanRight;
  375. //
  376. // skip pixels from left edge to left clip, while
  377. // incrementing gradient
  378. //
  379. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  380. if (GradientLeft > 0)
  381. {
  382. Red += dRed * GradientLeft;
  383. Green += dGreen * GradientLeft;
  384. Blue += dBlue * GradientLeft;
  385. }
  386. while (pDstX < pDstScanRight)
  387. {
  388. *pDstX = (BYTE)((Blue & 0x00ff0000) >> 16);
  389. *(pDstX+1) = (BYTE)((Green & 0x00ff0000) >> 16);
  390. *(pDstX+2) = (BYTE)((Red & 0x00ff0000) >> 16);
  391. Red += dRed;
  392. Green += dGreen;
  393. Blue += dBlue;
  394. pDstX+=3;
  395. }
  396. }
  397. pDst += lDelta;
  398. pEdge++;
  399. yScan++;
  400. }
  401. }
  402. /******************************Public*Routine******************************\
  403. * vFillDIB16_565
  404. *
  405. *
  406. * Arguments:
  407. *
  408. *
  409. *
  410. * Return Value:
  411. *
  412. *
  413. *
  414. * History:
  415. *
  416. * 11/21/1996 Mark Enstrom [marke]
  417. *
  418. \**************************************************************************/
  419. VOID
  420. vFillTriDIB16_565(
  421. PDIBINFO pDibInfo,
  422. PTRIANGLEDATA ptData
  423. )
  424. {
  425. LONG lDelta = pDibInfo->stride;
  426. LONG yScan = ptData->y0;
  427. LONG yScanBottom;
  428. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  429. PTRIEDGE pEdge = &ptData->TriEdge[0];
  430. LONG dRed = ptData->dRdX;
  431. LONG dGreen = ptData->dGdX;
  432. LONG dBlue = ptData->dBdX;
  433. ULONG Red;
  434. ULONG Green;
  435. ULONG Blue;
  436. PULONG pulDither;
  437. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  438. LONG yDitherOrg = ptData->ptDitherOrg.y;
  439. LONG xDitherOrg = ptData->ptDitherOrg.x;
  440. while(yScan < yScanBottom)
  441. {
  442. PUSHORT pusDstX;
  443. PUSHORT pusDstScanRight;
  444. pulDither = &gulDither32[0] + 4 * ((yScan+yDitherOrg) & 3);
  445. Red = pEdge->Red;
  446. Green = pEdge->Green;
  447. Blue = pEdge->Blue;
  448. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  449. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  450. if (xScanLeft < xScanRight)
  451. {
  452. pusDstX = (PUSHORT)pDst + xScanLeft;
  453. pusDstScanRight = (PUSHORT)pDst + xScanRight;
  454. //
  455. // skip pixels from left edge to left clip, while
  456. // incrementing gradient
  457. //
  458. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  459. if (GradientLeft > 0)
  460. {
  461. Red += dRed * GradientLeft;
  462. Green += dGreen * GradientLeft;
  463. Blue += dBlue * GradientLeft;
  464. }
  465. //
  466. // Gradient fill scan line with dither
  467. //
  468. while (pusDstX < pusDstScanRight)
  469. {
  470. ULONG ulDither = pulDither[(((ULONG)pusDstX >> 1)+xDitherOrg) & 3];
  471. BYTE iRed = (BYTE)(((Red >> 3) + ulDither) >> 16);
  472. BYTE iGreen = (BYTE)(((Green >> 2) + ulDither) >> 16);
  473. BYTE iBlue = (BYTE)(((Blue >> 3) + ulDither) >> 16);
  474. //
  475. // check for overflow
  476. //
  477. if (((iRed | iBlue) & 0xe0) || (iGreen & 0xc0))
  478. {
  479. if (iRed & 0xe0)
  480. {
  481. iRed = 0x1f;
  482. }
  483. if (iBlue & 0xe0)
  484. {
  485. iBlue = 0x1f;
  486. }
  487. if (iGreen & 0xc0)
  488. {
  489. iGreen = 0x3f;
  490. }
  491. }
  492. *pusDstX = rgb565(iRed,iGreen,iBlue);
  493. pusDstX++;
  494. Red += dRed;
  495. Green += dGreen;
  496. Blue += dBlue;
  497. }
  498. }
  499. pDst += lDelta;
  500. pEdge++;
  501. yScan++;
  502. }
  503. }
  504. /******************************Public*Routine******************************\
  505. * vFillTriDIB16_555
  506. *
  507. *
  508. * Arguments:
  509. *
  510. *
  511. *
  512. * Return Value:
  513. *
  514. *
  515. *
  516. * History:
  517. *
  518. * 11/21/1996 Mark Enstrom [marke]
  519. *
  520. \**************************************************************************/
  521. VOID
  522. vFillTriDIB16_555(
  523. PDIBINFO pDibInfo,
  524. PTRIANGLEDATA ptData
  525. )
  526. {
  527. LONG lDelta = pDibInfo->stride;
  528. LONG yScan = ptData->y0;
  529. LONG yScanBottom;
  530. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  531. PTRIEDGE pEdge = &ptData->TriEdge[0];
  532. LONG dRed = ptData->dRdX;
  533. LONG dGreen = ptData->dGdX;
  534. LONG dBlue = ptData->dBdX;
  535. ULONG Red;
  536. ULONG Green;
  537. ULONG Blue;
  538. PULONG pulDither;
  539. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  540. LONG yDitherOrg = ptData->ptDitherOrg.y;
  541. LONG xDitherOrg = ptData->ptDitherOrg.x;
  542. while(yScan < yScanBottom)
  543. {
  544. PUSHORT pusDstX;
  545. PUSHORT pusDstScanRight;
  546. pulDither = &gulDither32[0] + 4 * ((yScan+yDitherOrg) & 3);
  547. Red = pEdge->Red;
  548. Green = pEdge->Green;
  549. Blue = pEdge->Blue;
  550. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  551. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  552. if (xScanLeft < xScanRight)
  553. {
  554. pusDstX = (PUSHORT)pDst + xScanLeft;
  555. pusDstScanRight = (PUSHORT)pDst + xScanRight;
  556. //
  557. // skip pixels from left edge to left clip, while
  558. // incrementing gradient
  559. //
  560. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  561. if (GradientLeft > 0)
  562. {
  563. Red += dRed * GradientLeft;
  564. Green += dGreen * GradientLeft;
  565. Blue += dBlue * GradientLeft;
  566. }
  567. //
  568. // Gradient fill scan line with dither
  569. //
  570. while (pusDstX < pusDstScanRight)
  571. {
  572. ULONG ulDither = pulDither[(((ULONG)pusDstX >> 1)+xDitherOrg) & 3];
  573. BYTE iRed = (BYTE)(((Red >> 3) + ulDither) >> 16);
  574. BYTE iGreen = (BYTE)(((Green >> 3) + ulDither) >> 16);
  575. BYTE iBlue = (BYTE)(((Blue >> 3) + ulDither) >> 16);
  576. //
  577. // check for overflow
  578. //
  579. if ((iRed | iBlue | iGreen) & 0xe0)
  580. {
  581. if (iRed & 0xe0)
  582. {
  583. iRed = 0x1f;
  584. }
  585. if (iBlue & 0xe0)
  586. {
  587. iBlue = 0x1f;
  588. }
  589. if (iGreen & 0xe0)
  590. {
  591. iGreen = 0x1f;
  592. }
  593. }
  594. *pusDstX = rgb555(iRed,iGreen,iBlue);
  595. pusDstX++;
  596. Red += dRed;
  597. Green += dGreen;
  598. Blue += dBlue;
  599. }
  600. }
  601. pDst += lDelta;
  602. pEdge++;
  603. yScan++;
  604. }
  605. }
  606. /******************************Public*Routine******************************\
  607. * vFillDIB8
  608. *
  609. *
  610. * Arguments:
  611. *
  612. *
  613. *
  614. * Return Value:
  615. *
  616. *
  617. *
  618. * History:
  619. *
  620. * 11/21/1996 Mark Enstrom [marke]
  621. *
  622. \**************************************************************************/
  623. VOID
  624. vFillTriDIB8(
  625. PDIBINFO pDibInfo,
  626. PTRIANGLEDATA ptData
  627. )
  628. {
  629. LONG lDelta = pDibInfo->stride;
  630. LONG yScan = ptData->y0;
  631. LONG yScanBottom;
  632. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  633. PTRIEDGE pEdge = &ptData->TriEdge[0];
  634. LONG dRed = ptData->dRdX;
  635. LONG dGreen = ptData->dGdX;
  636. LONG dBlue = ptData->dBdX;
  637. ULONG Red;
  638. ULONG Green;
  639. ULONG Blue;
  640. PBYTE pxlate = pDibInfo->pxlate332;
  641. PBYTE pDitherMatrix;
  642. PBYTE pSaturationTable;
  643. //
  644. // get/build rgb to palette table
  645. //
  646. if (pxlate == NULL)
  647. {
  648. WARNING("vTriFillDIB8:Failed to generate rgb555 xlate table\n");
  649. return;
  650. }
  651. //
  652. // either use default palette or halftone palette dither
  653. //
  654. if (pxlate == gHalftoneColorXlate332)
  655. {
  656. pDitherMatrix = gDitherMatrix16x16Halftone;
  657. pSaturationTable = HalftoneSaturationTable;
  658. }
  659. else
  660. {
  661. pDitherMatrix = gDitherMatrix16x16Default;
  662. pSaturationTable = DefaultSaturationTable;
  663. }
  664. //
  665. // scan from top to bottom of triangle scan lines
  666. //
  667. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  668. LONG yDitherOrg = ptData->ptDitherOrg.y;
  669. LONG xDitherOrg = ptData->ptDitherOrg.x;
  670. while(yScan < yScanBottom)
  671. {
  672. PBYTE pjDstX;
  673. PBYTE pjDstScanRight,pjDstScanLeft;
  674. Red = pEdge->Red;
  675. Green = pEdge->Green;
  676. Blue = pEdge->Blue;
  677. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  678. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  679. PBYTE pDitherLevel = &pDitherMatrix[(16 * ((yScan+yDitherOrg) & DITHER_8_MASK_Y))];
  680. if (xScanLeft < xScanRight)
  681. {
  682. pjDstX = pDst + xScanLeft;
  683. pjDstScanRight = pDst + xScanRight;
  684. //
  685. // skip pixels from left edge to left clip, while
  686. // incrementing gradient
  687. //
  688. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  689. if (GradientLeft > 0)
  690. {
  691. Red += dRed * GradientLeft;
  692. Green += dGreen * GradientLeft;
  693. Blue += dBlue * GradientLeft;
  694. }
  695. //
  696. // gradient fill scan with dither
  697. //
  698. while (pjDstX < pjDstScanRight)
  699. {
  700. //
  701. // offset into dither array
  702. //
  703. BYTE jDitherMatrix = *(pDitherLevel + (((ULONG)pjDstX+xDitherOrg) & DITHER_8_MASK_X));
  704. ULONG iRed = (ULONG)((Red >> 16) & 0xff);
  705. ULONG iGreen = (ULONG)((Green >> 16) & 0xff);
  706. ULONG iBlue = (ULONG)((Blue >> 16) & 0xff);
  707. iRed = pSaturationTable[iRed + jDitherMatrix];
  708. iGreen = pSaturationTable[iGreen + jDitherMatrix];
  709. iBlue = pSaturationTable[iBlue + jDitherMatrix];
  710. BYTE jIndex;
  711. GRAD_PALETTE_MATCH(jIndex,pxlate,((BYTE)iRed),((BYTE)iGreen),((BYTE)iBlue));
  712. *pjDstX = jIndex;
  713. pjDstX++;
  714. Red += dRed;
  715. Green += dGreen;
  716. Blue += dBlue;
  717. }
  718. }
  719. pDst += lDelta;
  720. pEdge++;
  721. yScan++;
  722. }
  723. }
  724. /******************************Public*Routine******************************\
  725. * vFillDIB4
  726. *
  727. *
  728. * Arguments:
  729. *
  730. *
  731. *
  732. * Return Value:
  733. *
  734. *
  735. *
  736. * History:
  737. *
  738. * 11/21/1996 Mark Enstrom [marke]
  739. *
  740. \**************************************************************************/
  741. VOID
  742. vFillTriDIB4(
  743. PDIBINFO pDibInfo,
  744. PTRIANGLEDATA ptData
  745. )
  746. {
  747. LONG lDelta = pDibInfo->stride;
  748. LONG yScan = ptData->y0;
  749. LONG yScanBottom;
  750. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  751. PTRIEDGE pEdge = &ptData->TriEdge[0];
  752. LONG dRed = ptData->dRdX;
  753. LONG dGreen = ptData->dGdX;
  754. LONG dBlue = ptData->dBdX;
  755. ULONG Red;
  756. ULONG Green;
  757. ULONG Blue;
  758. PBYTE pDitherMatrix = gDitherMatrix16x16Default;
  759. PBYTE pSaturationTable = DefaultSaturationTable;
  760. PBYTE pxlate = pDibInfo->pxlate332;
  761. if (pxlate == NULL)
  762. {
  763. WARNING("Failed to generate rgb555 xlate table\n");
  764. return;
  765. }
  766. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  767. LONG yDitherOrg = ptData->ptDitherOrg.y;
  768. LONG xDitherOrg = ptData->ptDitherOrg.x;
  769. while(yScan < yScanBottom)
  770. {
  771. PBYTE pjDstX;
  772. LONG iDstX;
  773. Red = pEdge->Red;
  774. Green = pEdge->Green;
  775. Blue = pEdge->Blue;
  776. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  777. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  778. PBYTE pDitherLevel = &pDitherMatrix[(16 * ((yScan+yDitherOrg) & DITHER_8_MASK_Y))];
  779. if (xScanLeft < xScanRight)
  780. {
  781. pjDstX = pDst + (xScanLeft/2);
  782. iDstX = xScanLeft & 1;
  783. //
  784. // skip pixels from left edge to left clip, while
  785. // incrementing gradient
  786. //
  787. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  788. if (GradientLeft > 0)
  789. {
  790. Red += dRed * GradientLeft;
  791. Green += dGreen * GradientLeft;
  792. Blue += dBlue * GradientLeft;
  793. }
  794. //
  795. // fill scan line with dither
  796. //
  797. PALETTEENTRY palEntry;
  798. palEntry.peFlags = 2;
  799. while (xScanLeft < xScanRight)
  800. {
  801. //
  802. // offset into dither array
  803. //
  804. BYTE jDitherMatrix = *(pDitherLevel + ((xScanLeft+xDitherOrg) & DITHER_8_MASK_X));
  805. ULONG iRed = (ULONG)((Red >> 16) & 0xff);
  806. ULONG iGreen = (ULONG)((Green >> 16) & 0xff);
  807. ULONG iBlue = (ULONG)((Blue >> 16) & 0xff);
  808. iRed = pSaturationTable[iRed + jDitherMatrix];
  809. iGreen = pSaturationTable[iGreen + jDitherMatrix];
  810. iBlue = pSaturationTable[iBlue + jDitherMatrix];
  811. BYTE jIndex;
  812. GRAD_PALETTE_MATCH(jIndex,pxlate,((BYTE)iRed),((BYTE)iGreen),((BYTE)iBlue));
  813. //
  814. // write nibble
  815. //
  816. if (iDstX)
  817. {
  818. iDstX = 0;
  819. *pjDstX = (*pjDstX & 0xf0) | jIndex;
  820. pjDstX++;
  821. }
  822. else
  823. {
  824. *pjDstX = (*pjDstX & 0x0f) | (jIndex << 4);
  825. iDstX = 1;
  826. }
  827. xScanLeft++;
  828. Red += dRed;
  829. Green += dGreen;
  830. Blue += dBlue;
  831. }
  832. }
  833. pDst += lDelta;
  834. pEdge++;
  835. yScan++;
  836. }
  837. }
  838. /******************************Public*Routine******************************\
  839. * vFillDIB1
  840. *
  841. *
  842. * Arguments:
  843. *
  844. *
  845. *
  846. * Return Value:
  847. *
  848. *
  849. *
  850. * History:
  851. *
  852. * 11/21/1996 Mark Enstrom [marke]
  853. *
  854. \**************************************************************************/
  855. VOID
  856. vFillTriDIB1(
  857. PDIBINFO pDibInfo,
  858. PTRIANGLEDATA ptData
  859. )
  860. {
  861. LONG lDelta = pDibInfo->stride;
  862. LONG yScan = ptData->y0;
  863. LONG yScanBottom;
  864. PBYTE pDst = (PBYTE)pDibInfo->pvBase + lDelta * yScan;
  865. PTRIEDGE pEdge = &ptData->TriEdge[0];
  866. LONG dRed = ptData->dRdX;
  867. LONG dGreen = ptData->dGdX;
  868. LONG dBlue = ptData->dBdX;
  869. ULONG Red;
  870. ULONG Green;
  871. ULONG Blue;
  872. PBYTE pxlate = pDibInfo->pxlate332;
  873. PBYTE pDitherMatrix = gDitherMatrix16x16Default;
  874. //
  875. // must have palette xlate
  876. //
  877. if (pxlate == NULL)
  878. {
  879. WARNING("Failed to generate rgb555 xlate table\n");
  880. return;
  881. }
  882. yScanBottom = MIN(ptData->rcl.bottom,ptData->y1);
  883. LONG yDitherOrg = ptData->ptDitherOrg.y;
  884. LONG xDitherOrg = ptData->ptDitherOrg.x;
  885. while(yScan < yScanBottom)
  886. {
  887. PBYTE pjDstX;
  888. LONG iDstX;
  889. LONG ScanRight;
  890. LONG ScanLeft;
  891. LONG xScan;
  892. Red = pEdge->Red;
  893. Green = pEdge->Green;
  894. Blue = pEdge->Blue;
  895. LONG xScanLeft = MAX(pEdge->xLeft,ptData->rcl.left);
  896. LONG xScanRight = MIN(pEdge->xRight,ptData->rcl.right);
  897. PBYTE pDitherLevel = &pDitherMatrix[(16 * ((yScan+yDitherOrg) & DITHER_8_MASK_Y))];
  898. if (xScanLeft < xScanRight)
  899. {
  900. pjDstX = pDst + (xScanLeft/8);
  901. iDstX = xScanLeft & 7;
  902. //
  903. // skip clipped out portion of scan line whille
  904. // running color gradient
  905. //
  906. LONG GradientLeft = ptData->rcl.left - pEdge->xLeft;
  907. if (GradientLeft > 0)
  908. {
  909. Red += dRed * GradientLeft;
  910. Green += dGreen * GradientLeft;
  911. Blue += dBlue * GradientLeft;
  912. }
  913. PALETTEENTRY palEntry;
  914. palEntry.peFlags = 2;
  915. while (xScanLeft < xScanRight)
  916. {
  917. //
  918. // offset into dither array
  919. //
  920. BYTE jDitherMatrix = 2 * (*(pDitherLevel + ((xScanLeft+xDitherOrg) & DITHER_8_MASK_X)));
  921. ULONG iRed = (ULONG)((Red >> 16) & 0xff);
  922. ULONG iGreen = (ULONG)((Green >> 16) & 0xff);
  923. ULONG iBlue = (ULONG)((Blue >> 16) & 0xff);
  924. //
  925. // add dither and saturate. 1bpp non-optimized
  926. //
  927. iRed = iRed + jDitherMatrix;
  928. if (iRed >= 255)
  929. {
  930. iRed = 255;
  931. }
  932. else
  933. {
  934. iRed = 0;
  935. }
  936. iGreen = iGreen + jDitherMatrix;
  937. if (iGreen >= 255)
  938. {
  939. iGreen = 255;
  940. }
  941. else
  942. {
  943. iGreen = 0;
  944. }
  945. iBlue = iBlue + jDitherMatrix;
  946. if (iBlue >= 255)
  947. {
  948. iBlue = 255;
  949. }
  950. else
  951. {
  952. iBlue = 0;
  953. }
  954. BYTE jIndex;
  955. //
  956. // pjVector is known to be identity, so could make new macro for
  957. // palette_match_1 if perf ever an issue
  958. //
  959. GRAD_PALETTE_MATCH(jIndex,pxlate,((BYTE)iRed),((BYTE)iGreen),((BYTE)iBlue));
  960. //
  961. // write bit (!!! completely and totally non-optimized)
  962. //
  963. LONG iShift = 7 - iDstX;
  964. BYTE OrMask = 1 << iShift;
  965. BYTE AndMask = ~OrMask;
  966. jIndex = jIndex << iShift;
  967. *pjDstX = (*pjDstX & AndMask) | jIndex;
  968. iDstX++;
  969. if (iDstX == 8)
  970. {
  971. iDstX = 0;
  972. pjDstX++;
  973. }
  974. xScanLeft++;
  975. Red += dRed;
  976. Green += dGreen;
  977. Blue += dBlue;
  978. }
  979. }
  980. pDst += lDelta;
  981. pEdge++;
  982. yScan++;
  983. }
  984. }
  985. /******************************Public*Routine******************************\
  986. * DIBTriangleMesh
  987. *
  988. *
  989. * Arguments:
  990. *
  991. *
  992. *
  993. * Return Value:
  994. *
  995. *
  996. *
  997. * History:
  998. *
  999. * 12/4/1996 Mark Enstrom [marke]
  1000. *
  1001. \**************************************************************************/
  1002. BOOL
  1003. DIBTriangleMesh(
  1004. HDC hdc,
  1005. PTRIVERTEX pVertex,
  1006. ULONG nVertex,
  1007. PGRADIENT_TRIANGLE pMesh,
  1008. ULONG nMesh,
  1009. ULONG ulMode,
  1010. PRECTL prclPhysExt,
  1011. PDIBINFO pDibInfo,
  1012. PPOINTL pptlDitherOrg,
  1013. BOOL bReadable
  1014. )
  1015. {
  1016. BOOL bStatus = TRUE;
  1017. RECTL rclDst;
  1018. RECTL rclDstWk;
  1019. ULONG ulIndex;
  1020. PTRIANGLEDATA ptData = NULL;
  1021. PULONG pulDIB = NULL;
  1022. PFN_TRIFILL pfnTriFill = NULL;
  1023. pfnTriFill = pfnTriangleFillFunction(pDibInfo,bReadable);
  1024. if (pfnTriFill == NULL)
  1025. {
  1026. WARNING("DIBTriangleMesh:Can't draw to surface\n");
  1027. return(TRUE);
  1028. }
  1029. //
  1030. // work in physical map mode, restore before return
  1031. //
  1032. ULONG OldMode = SetMapMode(hdc,MM_TEXT);
  1033. //
  1034. // fake up scale !!!
  1035. //
  1036. for (ulIndex=0;ulIndex<nVertex;ulIndex++)
  1037. {
  1038. pVertex[ulIndex].x = pVertex[ulIndex].x * 16;
  1039. pVertex[ulIndex].y = pVertex[ulIndex].y * 16;
  1040. }
  1041. //
  1042. // limit recorded triangle to clipped output
  1043. //
  1044. LONG dxTri = prclPhysExt->right - prclPhysExt->left;
  1045. LONG dyTri = prclPhysExt->bottom - prclPhysExt->top;
  1046. //
  1047. // check for clipped out
  1048. //
  1049. if ((dyTri > 0) && (dxTri > 0))
  1050. {
  1051. //
  1052. // allocate structure to hold scan line data for all triangles
  1053. // drawn during this call
  1054. //
  1055. ptData = (PTRIANGLEDATA)LOCALALLOC(sizeof(TRIANGLEDATA) + (dyTri-1) * sizeof(TRIEDGE));
  1056. if (ptData != NULL)
  1057. {
  1058. //
  1059. // draw each triangle
  1060. //
  1061. ptData->rcl = *prclPhysExt;
  1062. ptData->DrawMode = ulMode;
  1063. ptData->ptDitherOrg = *pptlDitherOrg;
  1064. for (ulIndex=0;ulIndex<nMesh;ulIndex++)
  1065. {
  1066. ULONG ulTri1 = pMesh[ulIndex].Vertex1;
  1067. ULONG ulTri2 = pMesh[ulIndex].Vertex2;
  1068. ULONG ulTri3 = pMesh[ulIndex].Vertex3;
  1069. //
  1070. // make sure index are in array
  1071. //
  1072. if (
  1073. (ulTri1 > nVertex) ||
  1074. (ulTri2 > nVertex) ||
  1075. (ulTri3 > nVertex)
  1076. )
  1077. {
  1078. bStatus = FALSE;
  1079. break;
  1080. }
  1081. PTRIVERTEX pv0 = &pVertex[ulTri1];
  1082. PTRIVERTEX pv1 = &pVertex[ulTri2];
  1083. PTRIVERTEX pv2 = &pVertex[ulTri3];
  1084. PTRIVERTEX pvt;
  1085. if (pv0->y > pv1->y)
  1086. {
  1087. SWAP_VERTEX(pv0,pv1,pvt);
  1088. }
  1089. if (pv1->y > pv2->y)
  1090. {
  1091. SWAP_VERTEX(pv1,pv2,pvt);
  1092. }
  1093. if (pv0->y > pv1->y)
  1094. {
  1095. SWAP_VERTEX(pv0,pv1,pvt);
  1096. }
  1097. if (pv2->x > pv1->x)
  1098. {
  1099. SWAP_VERTEX(pv1,pv2,pvt);
  1100. }
  1101. //
  1102. // record triangle
  1103. //
  1104. bStatus = bCalculateTriangle(pv0,pv1,pv2,ptData);
  1105. if (bStatus)
  1106. {
  1107. //
  1108. // draw scan lines
  1109. //
  1110. (*pfnTriFill)(pDibInfo,ptData);
  1111. }
  1112. }
  1113. }
  1114. else
  1115. {
  1116. DbgPrint("DIBTriangleMesh:Failed alloc \n");
  1117. bStatus = FALSE;
  1118. }
  1119. //
  1120. // cleanup
  1121. //
  1122. if (ptData)
  1123. {
  1124. LOCALFREE(ptData);
  1125. }
  1126. if (pulDIB)
  1127. {
  1128. LOCALFREE(pulDIB);
  1129. }
  1130. }
  1131. SetMapMode(hdc,OldMode);
  1132. return(bStatus);
  1133. }
  1134. /******************************Public*Routine******************************\
  1135. * vCalcMeshExtent
  1136. *
  1137. *
  1138. * Arguments:
  1139. *
  1140. *
  1141. *
  1142. * Return Value:
  1143. *
  1144. *
  1145. *
  1146. * History:
  1147. *
  1148. * 12/3/1996 Mark Enstrom [marke]
  1149. *
  1150. \**************************************************************************/
  1151. VOID
  1152. vCalcMeshExtent(
  1153. PTRIVERTEX pVertex,
  1154. ULONG nVertex,
  1155. RECTL *prclExt
  1156. )
  1157. {
  1158. ULONG ulIndex;
  1159. LONG xmin = MAX_INT;
  1160. LONG xmax = MIN_INT;
  1161. LONG ymin = MAX_INT;
  1162. LONG ymax = MIN_INT;
  1163. for (ulIndex = 0;ulIndex < nVertex;ulIndex++)
  1164. {
  1165. if (pVertex[ulIndex].x < xmin)
  1166. {
  1167. xmin = pVertex[ulIndex].x;
  1168. }
  1169. if (pVertex[ulIndex].x > xmax)
  1170. {
  1171. xmax = pVertex[ulIndex].x;
  1172. }
  1173. if (pVertex[ulIndex].y < ymin)
  1174. {
  1175. ymin = pVertex[ulIndex].y;
  1176. }
  1177. if (pVertex[ulIndex].y > ymax)
  1178. {
  1179. ymax = pVertex[ulIndex].y;
  1180. }
  1181. }
  1182. prclExt->left = xmin;
  1183. prclExt->right = xmax;
  1184. prclExt->top = ymin;
  1185. prclExt->bottom = ymax;
  1186. }
  1187. /******************************Public*Routine******************************\
  1188. * bConvertVertexToPhysical
  1189. * !!! slow way to convert.
  1190. *
  1191. * Arguments:
  1192. *
  1193. *
  1194. *
  1195. * Return Value:
  1196. *
  1197. *
  1198. *
  1199. * History:
  1200. *
  1201. * 12/4/1996 Mark Enstrom [marke]
  1202. *
  1203. \**************************************************************************/
  1204. BOOL
  1205. bConvertVertexToPhysical(
  1206. HDC hdc,
  1207. PTRIVERTEX pVertex,
  1208. ULONG nVertex,
  1209. PTRIVERTEX pPhysVert)
  1210. {
  1211. ULONG ulIndex;
  1212. for (ulIndex = 0;ulIndex<nVertex;ulIndex++)
  1213. {
  1214. POINT pt;
  1215. pt.x = pVertex[ulIndex].x;
  1216. pt.y = pVertex[ulIndex].y;
  1217. if (!LPtoDP(hdc,&pt,1))
  1218. {
  1219. return(FALSE);
  1220. }
  1221. pPhysVert[ulIndex].x = pt.x;
  1222. pPhysVert[ulIndex].y = pt.y;
  1223. pPhysVert[ulIndex].Red = pVertex[ulIndex].Red;
  1224. pPhysVert[ulIndex].Green = pVertex[ulIndex].Green;
  1225. pPhysVert[ulIndex].Blue = pVertex[ulIndex].Blue;
  1226. pPhysVert[ulIndex].Alpha = pVertex[ulIndex].Alpha;
  1227. }
  1228. return(TRUE);
  1229. }
  1230. /******************************Public*Routine******************************\
  1231. * bGetRectRegionFromDC
  1232. *
  1233. * Use DCI to get the rectanglular region from a HDC. If the clipping is
  1234. * more complex then 1 rectangle then return false.
  1235. *
  1236. * Arguments:
  1237. *
  1238. * hdc - destination DC
  1239. * prcClip - Clip Rect, fill out if RECT clipping
  1240. *
  1241. * Return Value:
  1242. *
  1243. * TRUE if clip rect was filled
  1244. *
  1245. * History:
  1246. *
  1247. * 12/6/1996 Mark Enstrom [marke]
  1248. *
  1249. \**************************************************************************/
  1250. BOOL
  1251. bGetRectRegionFromDC(
  1252. HDC hdc,
  1253. PRECT prcClip
  1254. )
  1255. {
  1256. //
  1257. // visible region
  1258. //
  1259. BOOL bRet = FALSE;
  1260. DWORD dwSize = 0;
  1261. LPRGNDATA lpRgnData = NULL;
  1262. //
  1263. // init clip rect to NULL
  1264. //
  1265. dwSize = GetDCRegionData(hdc,dwSize,lpRgnData);
  1266. if (dwSize)
  1267. {
  1268. lpRgnData = (LPRGNDATA)LOCALALLOC(dwSize);
  1269. if (lpRgnData)
  1270. {
  1271. dwSize = GetDCRegionData(hdc,dwSize,lpRgnData);
  1272. if (dwSize)
  1273. {
  1274. if (lpRgnData->rdh.nCount == 1)
  1275. {
  1276. bRet = TRUE;
  1277. *prcClip = lpRgnData->rdh.rcBound;
  1278. }
  1279. }
  1280. LOCALFREE(lpRgnData);
  1281. }
  1282. }
  1283. return(bRet);
  1284. }
  1285. /******************************Public*Routine******************************\
  1286. * pfnTriangleFillFunction
  1287. *
  1288. * look at format to decide if DIBSection should be drawn directly
  1289. *
  1290. * 32 bpp RGB
  1291. * 32 bpp BGR
  1292. * 24 bpp
  1293. * 16 bpp 565
  1294. * 16 bpp 555
  1295. *
  1296. * Trangles are only filled in high color (no palette) surfaces
  1297. *
  1298. * Arguments:
  1299. *
  1300. * pDibInfo - information about destination surface
  1301. *
  1302. * Return Value:
  1303. *
  1304. * PFN_TRIFILL - triangle filling routine
  1305. *
  1306. * History:
  1307. *
  1308. * 12/6/1996 Mark Enstrom [marke]
  1309. *
  1310. \**************************************************************************/
  1311. PFN_TRIFILL
  1312. pfnTriangleFillFunction(
  1313. PDIBINFO pDibInfo,
  1314. BOOL bReadable
  1315. )
  1316. {
  1317. PFN_TRIFILL pfnRet = NULL;
  1318. PULONG pulMasks = (PULONG)&pDibInfo->pbmi->bmiColors[0];
  1319. //
  1320. // 32 bpp RGB
  1321. //
  1322. if (!bReadable)
  1323. {
  1324. pfnRet = vFillTriDIBUnreadable;
  1325. }
  1326. else if (
  1327. (pDibInfo->pbmi->bmiHeader.biBitCount == 32) &&
  1328. (pDibInfo->pbmi->bmiHeader.biCompression == BI_RGB)
  1329. )
  1330. {
  1331. pfnRet = vFillTriDIB32BGRA;
  1332. }
  1333. else if (
  1334. (pDibInfo->pbmi->bmiHeader.biBitCount == 32) &&
  1335. (pDibInfo->pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  1336. (pulMasks[0] == 0xff0000) &&
  1337. (pulMasks[1] == 0x00ff00) &&
  1338. (pulMasks[2] == 0x0000ff)
  1339. )
  1340. {
  1341. pfnRet = vFillTriDIB32BGRA;
  1342. }
  1343. else if (
  1344. (pDibInfo->pbmi->bmiHeader.biBitCount == 32) &&
  1345. (pDibInfo->pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  1346. (pulMasks[0] == 0x0000ff) &&
  1347. (pulMasks[1] == 0x00ff00) &&
  1348. (pulMasks[2] == 0xff0000)
  1349. )
  1350. {
  1351. pfnRet = vFillTriDIB32RGB;
  1352. }
  1353. else if (
  1354. (pDibInfo->pbmi->bmiHeader.biBitCount == 24) &&
  1355. (pDibInfo->pbmi->bmiHeader.biCompression == BI_RGB)
  1356. )
  1357. {
  1358. pfnRet = vFillTriDIB24RGB;
  1359. }
  1360. //
  1361. // 16 BPP
  1362. //
  1363. else if (
  1364. (pDibInfo->pbmi->bmiHeader.biBitCount == 16) &&
  1365. (pDibInfo->pbmi->bmiHeader.biCompression == BI_BITFIELDS)
  1366. )
  1367. {
  1368. //
  1369. // 565,555
  1370. //
  1371. if (
  1372. (pulMasks[0] == 0xf800) &&
  1373. (pulMasks[1] == 0x07e0) &&
  1374. (pulMasks[2] == 0x001f)
  1375. )
  1376. {
  1377. pfnRet = vFillTriDIB16_565;
  1378. }
  1379. else if (
  1380. (pulMasks[0] == 0x7c00) &&
  1381. (pulMasks[1] == 0x03e0) &&
  1382. (pulMasks[2] == 0x001f)
  1383. )
  1384. {
  1385. pfnRet = vFillTriDIB16_555;
  1386. }
  1387. }
  1388. else if (pDibInfo->pbmi->bmiHeader.biBitCount == 8)
  1389. {
  1390. pfnRet = vFillTriDIB8;
  1391. }
  1392. else if (pDibInfo->pbmi->bmiHeader.biBitCount == 4)
  1393. {
  1394. pfnRet = vFillTriDIB4;
  1395. }
  1396. else if (pDibInfo->pbmi->bmiHeader.biBitCount == 1)
  1397. {
  1398. pfnRet = vFillTriDIB1;
  1399. }
  1400. return(pfnRet);
  1401. }
  1402. /******************************Public*Routine******************************\
  1403. * WinTriangleMesh
  1404. * win95 emulation
  1405. *
  1406. * Arguments:
  1407. *
  1408. *
  1409. *
  1410. * Return Value:
  1411. *
  1412. *
  1413. *
  1414. * History:
  1415. *
  1416. * 12/3/1996 Mark Enstrom [marke]
  1417. *
  1418. \**************************************************************************/
  1419. BOOL
  1420. WinGradientFill(
  1421. HDC hdc,
  1422. PTRIVERTEX pLogVertex,
  1423. ULONG nVertex,
  1424. PVOID pMesh,
  1425. ULONG nMesh,
  1426. ULONG ulMode
  1427. )
  1428. {
  1429. //
  1430. // If the DC has a DIBSection selected, then draw direct to DIBSECTION.
  1431. // else copy the rectangle needed from the dst to a 32bpp temp buffer,
  1432. // draw into the buffer, then bitblt to dst.
  1433. //
  1434. // calc extents for drawing
  1435. //
  1436. // convert extents and points to physical
  1437. //
  1438. // if no global then
  1439. // create memory DC with dibsection of correct size
  1440. // copy dst into dibsection (if can't make clipping)
  1441. // draw physical into dibsection
  1442. // copy dibsection to destination
  1443. //
  1444. PBYTE pDIB;
  1445. RECTL rclPhysExt;
  1446. RECTL rclLogExt;
  1447. PRECTL prclClip;
  1448. BOOL bStatus = FALSE;
  1449. PFN_TRIFILL pfnTriFill;
  1450. DIBINFO dibInfoDst;
  1451. PALINFO palDst;
  1452. ULONG ulDIBMode = SOURCE_GRADIENT_TRI;
  1453. BOOL bReadable;
  1454. POINTL ptlDitherOrg = {0,0};
  1455. //
  1456. // validate params and buffers
  1457. //
  1458. if (ulMode & (GRADIENT_FILL_RECT_H | GRADIENT_FILL_RECT_V))
  1459. {
  1460. //
  1461. // if threre is only 1 rect, don't bother reading destination
  1462. // bits
  1463. //
  1464. //
  1465. // !!! make repeated calls in case nMesh != 1 to avoid
  1466. // reading surface???
  1467. //
  1468. if (nMesh == 1)
  1469. {
  1470. ulDIBMode = SOURCE_GRADIENT_RECT;
  1471. }
  1472. }
  1473. else if (!(ulMode & GRADIENT_FILL_TRIANGLE))
  1474. {
  1475. WARNING("Invalid mode in call to GradientFill\n");
  1476. // !!! set last error
  1477. return(FALSE);
  1478. }
  1479. PTRIVERTEX pPhysVertex = (PTRIVERTEX)LOCALALLOC(nVertex * sizeof(TRIVERTEX));
  1480. if (pPhysVertex != NULL)
  1481. {
  1482. //
  1483. // convert to physical
  1484. //
  1485. bStatus = bConvertVertexToPhysical(hdc,pLogVertex,nVertex,pPhysVertex);
  1486. if (bStatus)
  1487. {
  1488. //
  1489. // get logical extents
  1490. //
  1491. vCalcMeshExtent(pLogVertex,nVertex,&rclLogExt);
  1492. //
  1493. // convert to physical extents
  1494. //
  1495. rclPhysExt = rclLogExt;
  1496. LPtoDP(hdc,(LPPOINT)&rclPhysExt,2);
  1497. //
  1498. // Set DIB information, convert to physical
  1499. //
  1500. bStatus = bInitDIBINFO(hdc,
  1501. rclLogExt.left,
  1502. rclLogExt.top,
  1503. rclLogExt.right - rclLogExt.left,
  1504. rclLogExt.bottom - rclLogExt.top,
  1505. &dibInfoDst);
  1506. if (bStatus)
  1507. {
  1508. //
  1509. // get a destination DIB. For RECT Mode, the destination is not read.
  1510. //
  1511. bSetupBitmapInfos(&dibInfoDst, NULL);
  1512. bStatus = bGetDstDIBits(&dibInfoDst, &bReadable,ulDIBMode);
  1513. if (!((!bStatus) || (dibInfoDst.rclClipDC.left == dibInfoDst.rclClipDC.right)))
  1514. {
  1515. ULONG ulIndex;
  1516. //
  1517. // if 1,4,8 format then allocate rgb332 to palette xlate
  1518. //
  1519. ULONG BitCount = dibInfoDst.pbmi->bmiHeader.biBitCount;
  1520. if (BitCount <= 8)
  1521. {
  1522. ULONG NumPalEntries;
  1523. PBYTE pxlate = NULL;
  1524. switch (BitCount)
  1525. {
  1526. case 1:
  1527. NumPalEntries = 2;
  1528. break;
  1529. case 4:
  1530. NumPalEntries = 16;
  1531. if ((dibInfoDst.pbmi->bmiHeader.biClrUsed > 0) &&
  1532. (dibInfoDst.pbmi->bmiHeader.biClrUsed < 16))
  1533. {
  1534. NumPalEntries = dibInfoDst.pbmi->bmiHeader.biClrUsed;
  1535. }
  1536. break;
  1537. case 8:
  1538. NumPalEntries = 256;
  1539. if ((dibInfoDst.pbmi->bmiHeader.biClrUsed > 0) &&
  1540. (dibInfoDst.pbmi->bmiHeader.biClrUsed < 256))
  1541. {
  1542. NumPalEntries = dibInfoDst.pbmi->bmiHeader.biClrUsed;
  1543. }
  1544. break;
  1545. }
  1546. pxlate = pGenColorXform332((PULONG)(&dibInfoDst.pbmi->bmiColors[0]),NumPalEntries);
  1547. dibInfoDst.pxlate332 = pxlate;
  1548. if (pxlate == NULL)
  1549. {
  1550. WARNING("Failed to allocate xlate\n");
  1551. bStatus = FALSE;
  1552. }
  1553. }
  1554. if (bStatus)
  1555. {
  1556. if (dibInfoDst.hDIB)
  1557. {
  1558. //
  1559. // if temp surface has been allocated,
  1560. // subtract origin from points
  1561. //
  1562. for (ulIndex=0;ulIndex<nVertex;ulIndex++)
  1563. {
  1564. pPhysVertex[ulIndex].x -= dibInfoDst.ptlGradOffset.x;
  1565. pPhysVertex[ulIndex].y -= dibInfoDst.ptlGradOffset.y;
  1566. }
  1567. //
  1568. // clipping now in relation to temp DIB
  1569. //
  1570. rclPhysExt = dibInfoDst.rclDIB;
  1571. //
  1572. // adjust dither org
  1573. //
  1574. ptlDitherOrg.x = dibInfoDst.rclBounds.left;
  1575. ptlDitherOrg.y = dibInfoDst.rclBounds.top;
  1576. }
  1577. else
  1578. {
  1579. //
  1580. // clip extents to destination clip rect
  1581. //
  1582. if (rclPhysExt.left < dibInfoDst.rclClipDC.left)
  1583. {
  1584. rclPhysExt.left = dibInfoDst.rclClipDC.left;
  1585. }
  1586. if (rclPhysExt.right > dibInfoDst.rclClipDC.right)
  1587. {
  1588. rclPhysExt.right = dibInfoDst.rclClipDC.right;
  1589. }
  1590. if (rclPhysExt.top < dibInfoDst.rclClipDC.top)
  1591. {
  1592. rclPhysExt.top = dibInfoDst.rclClipDC.top;
  1593. }
  1594. if (rclPhysExt.bottom > dibInfoDst.rclClipDC.bottom)
  1595. {
  1596. rclPhysExt.bottom = dibInfoDst.rclClipDC.bottom;
  1597. }
  1598. }
  1599. if (
  1600. (ulMode & (GRADIENT_FILL_RECT_H | GRADIENT_FILL_RECT_V))
  1601. )
  1602. {
  1603. //
  1604. // draw gradient rectangles
  1605. //
  1606. bStatus = DIBGradientRect(hdc,pPhysVertex,nVertex,(PGRADIENT_RECT)pMesh,nMesh,ulMode,&rclPhysExt,&dibInfoDst,&ptlDitherOrg);
  1607. }
  1608. else if (ulMode == GRADIENT_FILL_TRIANGLE)
  1609. {
  1610. //
  1611. // draw triangles
  1612. //
  1613. bStatus = DIBTriangleMesh(hdc,pPhysVertex,nVertex,(PGRADIENT_TRIANGLE)pMesh,nMesh,ulMode,&rclPhysExt,&dibInfoDst,&ptlDitherOrg,bReadable);
  1614. }
  1615. //
  1616. // copy output to final dest if needed
  1617. //
  1618. if (bStatus && bReadable)
  1619. {
  1620. bStatus = bSendDIBINFO (hdc,&dibInfoDst);
  1621. }
  1622. }
  1623. }
  1624. }
  1625. vCleanupDIBINFO(&dibInfoDst);
  1626. }
  1627. LOCALFREE(pPhysVertex);
  1628. }
  1629. else
  1630. {
  1631. bStatus = FALSE;
  1632. }
  1633. //
  1634. //
  1635. //
  1636. return(bStatus);
  1637. }
  1638. #endif
  1639. /******************************Public*Routine******************************\
  1640. * TriangleMesh
  1641. *
  1642. *
  1643. * Arguments:
  1644. *
  1645. *
  1646. *
  1647. * Return Value:
  1648. *
  1649. *
  1650. *
  1651. * History:
  1652. *
  1653. * 12/3/1996 Mark Enstrom [marke]
  1654. *
  1655. \**************************************************************************/
  1656. BOOL
  1657. GradientFill(
  1658. HDC hdc,
  1659. PTRIVERTEX pVertex,
  1660. ULONG nVertex,
  1661. PVOID pMesh,
  1662. ULONG nMesh,
  1663. ULONG ulMode
  1664. )
  1665. {
  1666. BOOL bRet;
  1667. bRet = gpfnGradientFill(hdc,
  1668. pVertex,
  1669. nVertex,
  1670. pMesh,
  1671. nMesh,
  1672. ulMode
  1673. );
  1674. return(bRet);
  1675. }
  1676.