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.

948 lines
23 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. #if !(_WIN32_WINNT >= 0x500)
  17. //
  18. // temp global
  19. //
  20. HBITMAP hbmDefault;
  21. #if DBG
  22. ULONG DbgRecord = 0;
  23. #endif
  24. /******************************Public*Routine******************************\
  25. * vHorizontalLine
  26. *
  27. *
  28. * Arguments:
  29. *
  30. *
  31. *
  32. * Return Value:
  33. *
  34. *
  35. *
  36. * History:
  37. *
  38. * 11/20/1996 Mark Enstrom [marke]
  39. *
  40. \**************************************************************************/
  41. inline
  42. VOID
  43. vHorizontalLine(
  44. PTRIVERTEX pv1,
  45. PTRIVERTEX pv2,
  46. PTRIANGLEDATA ptData,
  47. PTRIDDA ptridda
  48. )
  49. {
  50. LONG yPosition = ptridda->N0 >> 4;
  51. LONG yIndex = yPosition - ptData->rcl.top;
  52. ptridda->L = ptridda->M0 >> 4;
  53. #if DBG
  54. if (DbgRecord >= 1)
  55. {
  56. DbgPrint("vCalculateLine:Horizontal Line: L = 0x%lx, yIndex = 0x%lx\n",ptridda->L,yIndex);
  57. }
  58. #endif
  59. if ((yPosition >= ptData->rcl.top) &&
  60. (yPosition < ptData->rcl.bottom))
  61. {
  62. //
  63. // find left edge
  64. //
  65. if (pv1->x <= pv2->x)
  66. {
  67. //
  68. // left edge
  69. // !!! is the check necessary? overlap from another
  70. // line segment.
  71. //
  72. ptData->TriEdge[yIndex].xLeft = pv1->x >> 4;
  73. ptData->TriEdge[yIndex].Red = pv1->Red << 8;
  74. ptData->TriEdge[yIndex].Green = pv1->Green << 8;
  75. ptData->TriEdge[yIndex].Blue = pv1->Blue << 8;
  76. ptData->TriEdge[yIndex].Alpha = pv1->Alpha << 8;
  77. //
  78. // right edge
  79. //
  80. ptData->TriEdge[yIndex].xRight = pv2->x >> 4;
  81. }
  82. else
  83. {
  84. //
  85. // left edge
  86. //
  87. ptData->TriEdge[yIndex].xLeft = pv2->x >> 4;
  88. ptData->TriEdge[yIndex].Red = pv2->Red << 8;
  89. ptData->TriEdge[yIndex].Green = pv2->Green << 8;
  90. ptData->TriEdge[yIndex].Blue = pv2->Blue << 8;
  91. ptData->TriEdge[yIndex].Alpha = pv2->Alpha << 8;
  92. //
  93. // right edge
  94. //
  95. ptData->TriEdge[yIndex].xRight = pv1->x >> 4;
  96. }
  97. }
  98. }
  99. /******************************Public*Routine******************************\
  100. * vLeftEdgeDDA
  101. *
  102. * Run line DDA down a left edge of the triangle recording left edge
  103. * position and color
  104. *
  105. * Arguments:
  106. *
  107. * NumScanLines
  108. * yIndex
  109. * Red
  110. * Green
  111. * Blue
  112. * Alpha
  113. * L
  114. * Rb
  115. *
  116. * Return Value:
  117. *
  118. * None
  119. *
  120. * History:
  121. *
  122. * 11/20/1996 Mark Enstrom [marke]
  123. *
  124. \**************************************************************************/
  125. inline
  126. VOID
  127. vLeftEdgeDDA(
  128. PTRIANGLEDATA ptData,
  129. PTRIDDA ptridda
  130. )
  131. {
  132. LONG NumScanLines = ptridda->NumScanLines;
  133. LONG yIndex = ptridda->yIndex;
  134. LONG Red = ptridda->Red;
  135. LONG Green = ptridda->Green;
  136. LONG Blue = ptridda->Blue;
  137. LONG Alpha = ptridda->Alpha;
  138. LONG L = ptridda->L;
  139. LONG Rb = ptridda->Rb;
  140. #if DBG
  141. if (DbgRecord >= 1)
  142. {
  143. DbgPrint("vLeftEdgeDDA:Scan yIndex = %li\n",yIndex);
  144. }
  145. #endif
  146. // Scan all lines, only record lines contained by
  147. // the clipping in ptData->rcl (y)
  148. while (NumScanLines--)
  149. {
  150. #if DBG
  151. if (DbgRecord >= 3)
  152. {
  153. DbgPrint("vCalculateLine:Scan yIndex = %li\n",yIndex);
  154. DbgPrint("vCalculateLine:L = %li\n",L);
  155. DbgPrint("vCalculateLine:Rb = %li\n",Rb);
  156. }
  157. #endif
  158. // record left edge
  159. if (yIndex >= 0)
  160. {
  161. ptData->TriEdge[yIndex].xLeft = L;
  162. ptData->TriEdge[yIndex].Red = Red;
  163. ptData->TriEdge[yIndex].Green = Green;
  164. ptData->TriEdge[yIndex].Blue = Blue;
  165. ptData->TriEdge[yIndex].Alpha = Alpha;
  166. }
  167. // inc y by one scan line, inc x(L) by integer step
  168. // and inc error term by dR
  169. yIndex++;
  170. L += ptridda->dL;
  171. Rb -= ptridda->dR;
  172. // inc color components by y and integer x components
  173. Red += (ptridda->dxyRed);
  174. Green += (ptridda->dxyGreen);
  175. Blue += (ptridda->dxyBlue);
  176. Alpha += (ptridda->dxyAlpha);
  177. // check for DDA error term overflow, add one
  178. // more step in x if true, and correct error term
  179. if (Rb < 0)
  180. {
  181. // DDA
  182. L += ptridda->Linc;
  183. Rb += ptridda->dN;
  184. // inc color components
  185. Red += ptData->dRdX;
  186. Green += ptData->dGdX;
  187. Blue += ptData->dBdX;
  188. Alpha += ptData->dAdX;
  189. }
  190. }
  191. }
  192. /******************************Public*Routine******************************\
  193. * vRightEdgeDDA
  194. *
  195. * Run the line DDA along the right edge of the triangle recording right
  196. * edge position
  197. *
  198. * Arguments:
  199. *
  200. * NumScanLines
  201. * yIndex
  202. * Red
  203. * Green
  204. * Blue
  205. * Alpha
  206. * L
  207. * Rb
  208. *
  209. * Return Value:
  210. *
  211. * None
  212. *
  213. * History:
  214. *
  215. * 11/25/1996 Mark Enstrom [marke]
  216. *
  217. \**************************************************************************/
  218. inline
  219. VOID
  220. vRightEdgeDDA(
  221. PTRIANGLEDATA ptData,
  222. PTRIDDA ptridda
  223. )
  224. {
  225. LONG NumScanLines = ptridda->NumScanLines;
  226. LONG yIndex = ptridda->yIndex;
  227. LONG Red = ptridda->Red;
  228. LONG Green = ptridda->Green;
  229. LONG Blue = ptridda->Blue;
  230. LONG Alpha = ptridda->Alpha;
  231. LONG L = ptridda->L;
  232. LONG Rb = ptridda->Rb;
  233. // Scan all lines, only record lines contained by
  234. // the clipping in ptData->rcl (y)
  235. #if DBG
  236. if (DbgRecord >= 1)
  237. {
  238. DbgPrint("vRightEdgeDDA:Scan yIndex = %li\n",yIndex);
  239. }
  240. #endif
  241. while (ptridda->NumScanLines--)
  242. {
  243. #if DBG
  244. if (DbgRecord >= 3)
  245. {
  246. DbgPrint("vCalculateLine:Scan yIndex = %li\n",yIndex);
  247. DbgPrint("vCalculateLine:L = %li\n",L);
  248. DbgPrint("vCalculateLine:Rb = %li\n",Rb);
  249. }
  250. #endif
  251. // record left, right edge
  252. if (yIndex >= 0)
  253. {
  254. ptData->TriEdge[yIndex].xRight = L;
  255. }
  256. // inc y by one scan line, inc x(L) by integer step
  257. // and inc error term by dR
  258. yIndex++;
  259. L += ptridda->dL;
  260. Rb -= ptridda->dR;
  261. // inc color components by y and integer x components
  262. Red += (ptridda->dxyRed);
  263. Green += (ptridda->dxyGreen);
  264. Blue += (ptridda->dxyBlue);
  265. Alpha += (ptridda->dxyAlpha);
  266. // check for DDA error term overflow, add one
  267. // more step in x if true, and correct error term
  268. if (Rb < 0)
  269. {
  270. // DDA
  271. L += ptridda->Linc;
  272. Rb += ptridda->dN;
  273. // inc color components
  274. Red += ptData->dRdX;
  275. Green += ptData->dGdX;
  276. Blue += ptData->dBdX;
  277. Alpha += ptData->dAdX;
  278. }
  279. }
  280. }
  281. /******************************Public*Routine******************************\
  282. * vCalulateLine
  283. *
  284. *
  285. * Arguments:
  286. *
  287. *
  288. *
  289. * Return Value:
  290. *
  291. *
  292. *
  293. * History:
  294. *
  295. * 11/20/1996 Mark Enstrom [marke]
  296. *
  297. \**************************************************************************/
  298. VOID
  299. vCalculateLine(
  300. PTRIVERTEX pv1,
  301. PTRIVERTEX pv2,
  302. PTRIANGLEDATA ptData,
  303. BOOL bLeftEdge
  304. )
  305. {
  306. TRIDDA tridda;
  307. //
  308. // initial y component
  309. //
  310. tridda.dxyRed = ptData->dRdY;
  311. tridda.dxyGreen = ptData->dGdY;
  312. tridda.dxyBlue = ptData->dBdY;
  313. tridda.dxyAlpha = ptData->dAdY;
  314. #if DBG
  315. if (DbgRecord >= 1)
  316. {
  317. DbgPrint("vCalculateLine:\n");
  318. DbgPrint("vCalculateLine:pv1.x = %li, pv1.y = %li\n",pv1->x,pv1->y);
  319. DbgPrint("vCalculateLine:pv1->Red = 0x%lx, pv1->Green = 0x%lx, pv1->Blue = 0x%lx\n",
  320. pv1->Red,pv1->Green,pv1->Blue);
  321. DbgPrint("vCalculateLine:pv2.x = %li, pv2.y = %li\n",pv2->x,pv2->y);
  322. DbgPrint("vCalculateLine:pv2->Red = 0x%lx, pv2->Green = 0x%lx, pv2->Blue = 0x%lx\n",
  323. pv2->Red,pv2->Green,pv2->Blue);
  324. }
  325. #endif
  326. //
  327. // Arrange lines, must run in positive delta y.
  328. // !!! what other effect of swap is there? !!!
  329. //
  330. if (pv2->y >= pv1->y)
  331. {
  332. tridda.dN = pv2->y - pv1->y;
  333. tridda.dM = pv2->x - pv1->x;
  334. tridda.N0 = pv1->y;
  335. tridda.M0 = pv1->x;
  336. tridda.Red = pv1->Red << 8;
  337. tridda.Green = pv1->Green << 8;
  338. tridda.Blue = pv1->Blue << 8;
  339. tridda.Alpha = pv1->Alpha << 8;
  340. }
  341. else
  342. {
  343. tridda.dN = pv1->y - pv2->y;
  344. tridda.dM = pv1->x - pv2->x;
  345. tridda.N0 = pv2->y;
  346. tridda.M0 = pv2->x;
  347. tridda.Red = pv2->Red << 8;
  348. tridda.Green = pv2->Green << 8;
  349. tridda.Blue = pv2->Blue << 8;
  350. tridda.Alpha = pv2->Alpha << 8;
  351. tridda.dxyRed = -tridda.dxyRed;
  352. tridda.dxyGreen = -tridda.dxyGreen;
  353. tridda.dxyBlue = -tridda.dxyBlue;
  354. tridda.dxyAlpha = -tridda.dxyAlpha;
  355. }
  356. //
  357. // Check for horizontal line, dN == 0 is a horizontal line.
  358. // In this case just record the end points.
  359. //
  360. if (tridda.dN == 0)
  361. {
  362. vHorizontalLine(pv1,pv2,ptData,&tridda);
  363. }
  364. else
  365. {
  366. //
  367. // this is as cryptic as ASM at the moment
  368. //
  369. LONG l0,Frac;
  370. tridda.Linc = 1;
  371. //
  372. // yIndex is the offset into the edge array for
  373. // the current line
  374. //
  375. tridda.yIndex = (tridda.N0 >> 4) - ptData->y0;
  376. tridda.NumScanLines = (tridda.dN >> 4);
  377. LONG NMax = (tridda.N0 >> 4) + tridda.NumScanLines;
  378. //
  379. // make sure scan lines do not overrun buffer due to
  380. // clipping
  381. //
  382. if (
  383. ((tridda.N0 >> 4) > ptData->rcl.bottom) ||
  384. (NMax < ptData->rcl.top)
  385. )
  386. {
  387. // nothing to draw
  388. return;
  389. }
  390. else if (NMax > ptData->rcl.bottom)
  391. {
  392. tridda.NumScanLines = tridda.NumScanLines - (NMax - ptData->rcl.bottom);
  393. }
  394. tridda.j = tridda.N0 >> 4;
  395. tridda.C = ((LONGLONG)tridda.M0 * (LONGLONG)tridda.dN) - ((LONGLONG)tridda.N0 * (LONGLONG)tridda.dM) -1;
  396. tridda.C = (tridda.C >> 4) + tridda.dN;
  397. LONGLONG LongL;
  398. if (tridda.dM > 0)
  399. {
  400. tridda.dL = tridda.dM / tridda.dN;
  401. tridda.dR = tridda.dM - tridda.dL * tridda.dN;
  402. }
  403. else if (tridda.dM < 0)
  404. {
  405. // negative divide
  406. LONG dLQ,dLR;
  407. tridda.dM = -tridda.dM;
  408. dLQ = (tridda.dM - 1) / tridda.dN;
  409. dLR = tridda.dM - 1 - (dLQ * tridda.dN);
  410. tridda.dL = -(dLQ + 1);
  411. tridda.dR = tridda.dN - dLR - 1;
  412. }
  413. else
  414. {
  415. // dM = 0
  416. tridda.dL = 0;
  417. tridda.dR = 0;
  418. }
  419. l0 = tridda.j * tridda.dL;
  420. LongL = tridda.j * tridda.dR + tridda.C;
  421. if (LongL > 0)
  422. {
  423. Frac = (LONG)(LongL/tridda.dN); // integer portion
  424. }
  425. else if (LongL < 0)
  426. {
  427. LONG Q = (LONG)((-LongL - 1)/tridda.dN);
  428. Frac = -(Q + 1);
  429. }
  430. else
  431. {
  432. Frac = 0;
  433. }
  434. tridda.R = (LONG)(LongL - (Frac * tridda.dN));
  435. tridda.L = l0 + Frac;
  436. tridda.Rb = tridda.dN - tridda.R - 1;
  437. //
  438. // Calculate color steps for dx !!! could it be more expensive !!!
  439. //
  440. if (tridda.dL != 0)
  441. {
  442. tridda.dxyRed = tridda.dxyRed + (LONG)((ptData->dRdXA * tridda.dL) / ptData->Area);
  443. tridda.dxyGreen = tridda.dxyGreen + (LONG)((ptData->dGdXA * tridda.dL) / ptData->Area);
  444. tridda.dxyBlue = tridda.dxyBlue + (LONG)((ptData->dBdXA * tridda.dL) / ptData->Area);
  445. tridda.dxyAlpha = tridda.dxyAlpha + (LONG)((ptData->dAdXA * tridda.dL) / ptData->Area);
  446. }
  447. #if DBG
  448. if (DbgRecord >= 1)
  449. {
  450. LONG CL = (LONG)tridda.C;
  451. LONG CH = (LONG)(tridda.C/4294967296);
  452. DbgPrint("vCalculateLine:Normal Line\n");
  453. DbgPrint("vCalculateLine:N0 = %li\n",tridda.N0);
  454. DbgPrint("vCalculateLine:dN = %li\n",tridda.dN);
  455. DbgPrint("vCalculateLine:M0 = %li\n",tridda.M0);
  456. DbgPrint("vCalculateLine:dM = %li\n",tridda.dM);
  457. DbgPrint("vCalculateLine:C = %08lx %08lx\n",CH,CL);
  458. DbgPrint("vCalculateLine:Frac = %li\n",Frac);
  459. DbgPrint("vCalculateLine:l0 = %li\n",l0);
  460. DbgPrint("vCalculateLine:L = %li\n",tridda.L);
  461. DbgPrint("vCalculateLine:dL = %li\n",tridda.dL);
  462. DbgPrint("vCalculateLine:R = %li\n",tridda.R);
  463. DbgPrint("vCalculateLine:dR = %li\n",tridda.dR);
  464. DbgPrint("vCalculateLine:Rb = %li\n",tridda.Rb);
  465. DbgPrint("vCalculateLine:dxyRed = 0x%lx\n",tridda.dxyRed);
  466. DbgPrint("vCalculateLine:dxyGreen = 0x%lx\n",tridda.dxyGreen);
  467. DbgPrint("vCalculateLine:dxyBlue = 0x%lx\n",tridda.dxyBlue);
  468. DbgPrint("vCalculateLine:dxyAlpha = 0x%lx\n",tridda.dxyAlpha);
  469. }
  470. #endif
  471. //
  472. // left or right edge
  473. //
  474. if (bLeftEdge)
  475. {
  476. vLeftEdgeDDA(ptData,&tridda);
  477. }
  478. else
  479. {
  480. vRightEdgeDDA(ptData,&tridda);
  481. }
  482. }
  483. }
  484. /******************************Public*Routine******************************\
  485. * vCalulateColorGradient
  486. *
  487. *
  488. * Arguments:
  489. *
  490. *
  491. *
  492. * Return Value:
  493. *
  494. *
  495. *
  496. * History:
  497. *
  498. * 11/20/1996 Mark Enstrom [marke]
  499. *
  500. \**************************************************************************/
  501. VOID
  502. vCalulateColorGradient(
  503. PTRIVERTEX pv0,
  504. PTRIVERTEX pv1,
  505. PTRIVERTEX pv2,
  506. LONG C0,
  507. LONG C1,
  508. LONG C2,
  509. PLONGLONG pArea,
  510. PLONGLONG pGradXA,
  511. PLONG pGradX,
  512. PLONG pGradY
  513. )
  514. {
  515. LONG dCdX = 0;
  516. LONG dCdY = 0;
  517. LONGLONG t1,t2,t3,tAll;
  518. C0 = C0 << 8;
  519. C1 = C1 << 8;
  520. C2 = C2 << 8;
  521. //
  522. // dY
  523. //
  524. t1 = - ((LONGLONG)C0 * (LONGLONG)(pv2->x - pv1->x));
  525. t2 = - ((LONGLONG)C1 * (LONGLONG)(pv0->x - pv2->x));
  526. t3 = - ((LONGLONG)C2 * (LONGLONG)(pv1->x - pv0->x));
  527. tAll = 16 * (t1 + t2 + t3);
  528. if (tAll > 0)
  529. {
  530. dCdY = (LONG)(tAll / *pArea);
  531. }
  532. else if (tAll < 0)
  533. {
  534. tAll = -tAll;
  535. dCdY = (LONG)((tAll - 1) / *pArea);
  536. dCdY = -(dCdY + 1);
  537. }
  538. *pGradY = dCdY;
  539. //
  540. // Divide by area to get single step x. Keep undivided
  541. // value around to calc multiple integer step in x
  542. //
  543. t1 = - ((LONGLONG)C0 * (LONGLONG)(pv2->y - pv1->y));
  544. t2 = - ((LONGLONG)C1 * (LONGLONG)(pv0->y - pv2->y));
  545. t3 = - ((LONGLONG)C2 * (LONGLONG)(pv1->y - pv0->y));
  546. tAll = t1;
  547. tAll += t2;
  548. tAll += t3;
  549. tAll *= 16;
  550. *pGradXA = tAll;
  551. dCdX = 0;
  552. if (tAll > 0)
  553. {
  554. dCdX = (LONG)(tAll / *pArea);
  555. }
  556. else if (tAll < 0)
  557. {
  558. tAll = -tAll;
  559. dCdX = (LONG)((tAll - 1) / *pArea);
  560. dCdX = -(dCdX + 1);
  561. }
  562. *pGradX = dCdX;
  563. }
  564. /******************************Public*Routine******************************\
  565. * vCalculateTriangle
  566. *
  567. * Calculate color gradients, then scan the three lines that make up the
  568. * triangle. Fill out a structure that can later be used to fill in the
  569. * interior of the triangle.
  570. *
  571. * Arguments:
  572. *
  573. *
  574. *
  575. * Return Value:
  576. *
  577. *
  578. *
  579. * History:
  580. *
  581. * 17-Jul-1996 -by- Mark Enstrom [marke]
  582. *
  583. \**************************************************************************/
  584. BOOL
  585. bCalculateTriangle(
  586. PTRIVERTEX pv0,
  587. PTRIVERTEX pv1,
  588. PTRIVERTEX pv2,
  589. PTRIANGLEDATA ptData
  590. )
  591. {
  592. LONG index;
  593. #if DBG
  594. if (DbgRecord >= 1)
  595. {
  596. DbgPrint("vCalculateTriangle:\n");
  597. DbgPrint("vCalculateTriangle:rcl = [%li,%li] to [%li,%li]\n",
  598. ptData->rcl.left,
  599. ptData->rcl.top,
  600. ptData->rcl.right,
  601. ptData->rcl.bottom
  602. );
  603. DbgPrint("vCalculateTriangle:pv0.x = %li, pv0.y = %li\n",pv0->x,pv0->y);
  604. DbgPrint("vCalculateTriangle:pv0->Red = 0x%lx, pv0->Green = 0x%lx, pv0->Blue = 0x%lx\n",
  605. pv0->Red,pv0->Green,pv0->Blue);
  606. DbgPrint("vCalculateTriangle:pv1.x = %li, pv1.y = %li\n",pv1->x,pv1->y);
  607. DbgPrint("vCalculateTriangle:pv1->Red = 0x%lx, pv1->Green = 0x%lx, pv1->Blue = 0x%lx\n",
  608. pv1->Red,pv1->Green,pv1->Blue);
  609. DbgPrint("vCalculateTriangle:pv2.x = %li, pv2.y = %li\n",pv2->x,pv2->y);
  610. DbgPrint("vCalculateTriangle:pv2->Red = 0x%lx, pv2->Green = 0x%lx, pv2->Blue = 0x%lx\n",
  611. pv2->Red,pv2->Green,pv2->Blue);
  612. }
  613. #endif
  614. //
  615. // calc area, color gradients in x,y
  616. //
  617. // area = (v2-v0) X (v1 - v2)
  618. //
  619. LONGLONG v12x = pv1->x - pv2->x;
  620. LONGLONG v12y = pv1->y - pv2->y;
  621. LONGLONG v02x = pv0->x - pv2->x;
  622. LONGLONG v02y = pv0->y - pv2->y;
  623. LONGLONG Area = (v12y * v02x) - (v12x * v02y);
  624. ptData->Area = Area;
  625. #if DBG
  626. if (DbgRecord >= 1)
  627. {
  628. LONG AreaL = (LONG)Area;
  629. LONG AreaH = (LONG)(Area/4294967296);
  630. DbgPrint("vCalculateTriangle:v12x = %lx\n",v12x);
  631. DbgPrint("vCalculateTriangle:v12y = %lx\n",v12y);
  632. DbgPrint("vCalculateTriangle:v02x = %lx\n",v02x);
  633. DbgPrint("vCalculateTriangle:v02y = %lx\n",v02y);
  634. DbgPrint("vCalculateTriangle:Area = %lx %lx\n",AreaH,AreaL);
  635. }
  636. #endif
  637. //
  638. // if area is zero then this is a degenerate triangle
  639. //
  640. if (Area == 0)
  641. {
  642. return(FALSE);
  643. }
  644. //
  645. // calc min and max drawing y
  646. //
  647. ptData->y0 = MAX((pv0->y >> 4),ptData->rcl.top);
  648. LONG MaxY = (MAX(pv1->y,pv2->y)) >> 4;
  649. ptData->y1 = MIN(MaxY,ptData->rcl.bottom);
  650. //
  651. // calculate color gradients for each color. There is a little redundant
  652. // work here with calculation of deltas. Should make this one call or
  653. // do it in place.
  654. //
  655. vCalulateColorGradient(pv0,pv1,pv2,pv0->Red ,pv1->Red ,pv2->Red ,&Area,&ptData->dRdXA,&ptData->dRdX,&ptData->dRdY);
  656. vCalulateColorGradient(pv0,pv1,pv2,pv0->Green,pv1->Green,pv2->Green,&Area,&ptData->dGdXA,&ptData->dGdX,&ptData->dGdY);
  657. vCalulateColorGradient(pv0,pv1,pv2,pv0->Blue ,pv1->Blue ,pv2->Blue ,&Area,&ptData->dBdXA,&ptData->dBdX,&ptData->dBdY);
  658. vCalulateColorGradient(pv0,pv1,pv2,pv0->Alpha,pv1->Alpha,pv2->Alpha,&Area,&ptData->dAdXA,&ptData->dAdX,&ptData->dAdY);
  659. #if DBG
  660. if (DbgRecord >= 1)
  661. {
  662. DbgPrint("vCalculateTriangle:dRdx = 0x%lx,dRdy = 0x%lx\n",ptData->dRdX,ptData->dRdY);
  663. DbgPrint("vCalculateTriangle:dGdx = 0x%lx,dGdy = 0x%lx\n",ptData->dGdX,ptData->dGdY);
  664. DbgPrint("vCalculateTriangle:dBdx = 0x%lx,dBdy = 0x%lx\n",ptData->dBdX,ptData->dBdY);
  665. DbgPrint("vCalculateTriangle:dAdx = 0x%lx,dAdy = 0x%lx\n",ptData->dAdX,ptData->dAdY);
  666. }
  667. #endif
  668. //
  669. // draw lines into data array
  670. //
  671. vCalculateLine(pv0,pv1,ptData,FALSE);
  672. vCalculateLine(pv1,pv2,ptData,(pv1->y > pv2->y));
  673. vCalculateLine(pv2,pv0,ptData,TRUE);
  674. return(TRUE);
  675. }
  676. /**************************************************************************\
  677. * bCalculateTriangle
  678. *
  679. *
  680. * Arguments:
  681. *
  682. *
  683. *
  684. * Return Value:
  685. *
  686. *
  687. *
  688. * History:
  689. *
  690. * 2/12/1997 Mark Enstrom [marke]
  691. *
  692. \**************************************************************************/
  693. BYTE
  694. GetNearestEntry(
  695. PULONG prgbIn,
  696. ULONG ulNumEntries,
  697. ALPHAPIX MatchColor
  698. )
  699. {
  700. LONG lError = MAX_INT;
  701. ULONG ulBest = 0;
  702. ULONG ulIndex;
  703. LPRGBQUAD prgb = (LPRGBQUAD)prgbIn;
  704. for (ulIndex=0;ulIndex<ulNumEntries;ulIndex++)
  705. {
  706. LONG eRed = (LONG)(MatchColor.pix.r - prgb->rgbRed);
  707. LONG eGreen = (LONG)(MatchColor.pix.g - prgb->rgbGreen);
  708. LONG eBlue = (LONG)(MatchColor.pix.b - prgb->rgbBlue);
  709. eRed = eRed*eRed + eGreen*eGreen + eBlue*eBlue;
  710. if (eRed < lError)
  711. {
  712. lError = eRed;
  713. ulBest = ulIndex;
  714. }
  715. prgb++;
  716. }
  717. return((BYTE)ulBest);
  718. }
  719. /**************************************************************************\
  720. * GenColorXform332
  721. *
  722. *
  723. * Arguments:
  724. *
  725. *
  726. *
  727. * Return Value:
  728. *
  729. *
  730. *
  731. * History:
  732. *
  733. * 2/12/1997 Mark Enstrom [marke]
  734. *
  735. \**************************************************************************/
  736. PBYTE
  737. pGenColorXform332(
  738. PULONG ppalIn,
  739. ULONG ulNumEntries
  740. )
  741. {
  742. ASSERTGDI((ppalIn != NULL),"pGenColorXform332 called with NULL input palette\n");
  743. ASSERTGDI((ulNumEntries <= 256),"pGenColorXform332 called with invalid ulNumEntries\n");
  744. if ((ppalIn == NULL) || (ulNumEntries > 256))
  745. {
  746. return(FALSE);
  747. }
  748. //
  749. // check for halftone palette
  750. //
  751. if (ulNumEntries == 256)
  752. {
  753. if (bIsHalftonePalette(ppalIn))
  754. {
  755. return(gHalftoneColorXlate332);
  756. }
  757. }
  758. //
  759. // allocate and generate color lookup table
  760. //
  761. PBYTE pxlate = (PBYTE)LOCALALLOC(256);
  762. if (pxlate)
  763. {
  764. PBYTE pXlateTable = pxlate;
  765. //
  766. // generate color xlate from RGB 332 to palette
  767. //
  768. BYTE Red[8] = {0,37,73,110,146,183,219,255};
  769. BYTE Green[8] = {0,37,73,110,146,183,219,255};
  770. BYTE Blue[4] = {0,85,171,255};
  771. //
  772. // ppalOut must be a 256 entry table
  773. //
  774. ULONG ulB,ulG,ulR;
  775. ALPHAPIX Pixel;
  776. for (ulR = 0;ulR<8;ulR++)
  777. {
  778. Pixel.pix.r = Red[ulR];
  779. for (ulG = 0;ulG<8;ulG++)
  780. {
  781. Pixel.pix.g = Green[ulG];
  782. for (ulB = 0;ulB<4;ulB++)
  783. {
  784. Pixel.pix.b = Blue[ulB];
  785. *pXlateTable++ = GetNearestEntry(ppalIn,ulNumEntries,Pixel);
  786. }
  787. }
  788. }
  789. }
  790. return(pxlate);
  791. }
  792. #endif