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.

3723 lines
111 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pattern.cxx
  3. *
  4. * This contains the special case blting code for P, Pn, DPx and Dn rops
  5. * with patterns.
  6. *
  7. * Created: 07-Mar-1992 13:12:58
  8. * Author: Donald Sidoroff [donalds]
  9. *
  10. * Copyright (c) 1992-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. ULONG aulLeftMask[] =
  14. {
  15. 0xFFFFFFFF,
  16. 0xFFFFFF00,
  17. 0xFFFF0000,
  18. 0xFF000000
  19. };
  20. #define DBG_PAT_CPY 0
  21. #if DBG_PAT_CPY
  22. ULONG DbgPatCpy = 0;
  23. #endif
  24. /******************************Public*Routine******************************\
  25. * vPatCpyRect8
  26. *
  27. * Tiles a pattern to 8/16/24 and 32 bpp bitmaps
  28. *
  29. * History:
  30. * 25-Jan-1992 -by- Donald Sidoroff [donalds]
  31. * Wrote it.
  32. \**************************************************************************/
  33. VOID vPatCpyRect8(PATBLTFRAME *ppbf)
  34. {
  35. FETCHFRAME ff;
  36. ULONG *pulTrg;
  37. ULONG cLeft;
  38. ULONG cRght;
  39. ULONG iLeft;
  40. ULONG iRght;
  41. ULONG ulLeft;
  42. ULONG ulRght;
  43. ULONG yPat;
  44. LONG yTrg;
  45. LONG xLeft;
  46. LONG yTop;
  47. BOOL bSimple = FALSE;
  48. cLeft = ((RECTL *) ppbf->pvObj)->left * ppbf->cMul;
  49. cRght = ((RECTL *) ppbf->pvObj)->right * ppbf->cMul;
  50. iLeft = cLeft & 3;
  51. iRght = cRght & 3;
  52. ulLeft = aulLeftMask[iLeft];
  53. ulRght = ~aulLeftMask[iRght];
  54. cLeft &= ~3; // Align to DWORD
  55. cRght &= ~3; // Align to DWORD
  56. // Compute the correct starting point in the pattern:
  57. xLeft = cLeft - ppbf->xPat;
  58. if (xLeft < 0)
  59. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  60. else xLeft %= ppbf->cxPat;
  61. yTop = ((RECTL *) ppbf->pvObj)->top - ppbf->yPat;
  62. if (yTop < 0)
  63. yTop = (ppbf->cyPat-1) - ((-yTop-1) % ppbf->cyPat);
  64. else yTop %= ppbf->cyPat;
  65. // If these are the same DWORD, then only one strip will be needed.
  66. // Merge the two masks together and just do the left edge.
  67. if (cLeft == cRght)
  68. {
  69. ulLeft &= ulRght;
  70. bSimple = TRUE;
  71. }
  72. // Lay down left edge, if needed.
  73. if (bSimple || (iLeft != 0))
  74. {
  75. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  76. yPat = yTop;
  77. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  78. ff.xPat = xLeft;
  79. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  80. {
  81. *pulTrg = (*pulTrg & ~ulLeft) | (FETCHMISALIGNED(&ff) & ulLeft);
  82. yPat++;
  83. ASSERTGDI(yPat<=ppbf->cyPat, "vPatCpyRect8: Reading past the end of the pattern.\n");
  84. if (yPat == ppbf->cyPat)
  85. {
  86. ff.pvPat = ppbf->pvPat;
  87. yPat = 0;
  88. }
  89. else
  90. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  91. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  92. }
  93. if (bSimple)
  94. return;
  95. cLeft += sizeof(DWORD); // Move to next DWORD
  96. xLeft += sizeof(DWORD); // Move to next DWORD
  97. }
  98. ff.culFill = (cRght - cLeft) >> 2;
  99. // Lay down center stripe, if needed.
  100. if (ff.culFill != 0)
  101. {
  102. yPat = yTop;
  103. xLeft %= ppbf->cxPat;
  104. ff.pvTrg = (PVOID) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  105. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  106. ff.cxPat = ppbf->cxPat;
  107. ff.xPat = xLeft;
  108. ff.culWidth = ppbf->cxPat;
  109. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  110. {
  111. ff.culWidth >>= 2;
  112. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  113. {
  114. vFetchAndCopy(&ff);
  115. yPat++;
  116. ASSERTGDI(yPat<=ppbf->cyPat, "vPatCpyRect8: Reading past the end of the pattern.\n");
  117. if (yPat == ppbf->cyPat)
  118. {
  119. ff.pvPat = ppbf->pvPat;
  120. yPat = 0;
  121. }
  122. else
  123. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  124. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  125. }
  126. }
  127. else
  128. {
  129. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  130. {
  131. vFetchShiftAndCopy(&ff);
  132. yPat++;
  133. ASSERTGDI(yPat<=ppbf->cyPat, "vPatCpyRect8: Reading past the end of the pattern.\n");
  134. if (yPat == ppbf->cyPat)
  135. {
  136. ff.pvPat = ppbf->pvPat;
  137. yPat = 0;
  138. }
  139. else
  140. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  141. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  142. ff.xPat = xLeft; // vFetchShift nukes this
  143. }
  144. }
  145. }
  146. // Lay down right edge, if needed.
  147. if (iRght != 0)
  148. {
  149. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cRght);
  150. yPat = yTop;
  151. xLeft += (ff.culFill * sizeof(DWORD));
  152. xLeft %= ppbf->cxPat;
  153. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  154. ff.xPat = xLeft;
  155. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  156. {
  157. *pulTrg = (*pulTrg & ~ulRght) | (FETCHMISALIGNED(&ff) & ulRght);
  158. yPat++;
  159. ASSERTGDI(yPat<=ppbf->cyPat, "vPatCpyRect8: Reading past the end of the pattern.\n");
  160. if (yPat == ppbf->cyPat)
  161. {
  162. ff.pvPat = ppbf->pvPat;
  163. yPat = 0;
  164. }
  165. else
  166. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  167. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  168. }
  169. }
  170. }
  171. /******************************Public*Routine******************************\
  172. * vPatNotRect8
  173. *
  174. * Tiles a pattern to 8/16/24 and 32 bpp bitmaps
  175. *
  176. * History:
  177. * 25-Jan-1992 -by- Donald Sidoroff [donalds]
  178. * Wrote it.
  179. \**************************************************************************/
  180. VOID vPatNotRect8(PATBLTFRAME *ppbf)
  181. {
  182. FETCHFRAME ff;
  183. ULONG *pulTrg;
  184. ULONG cLeft;
  185. ULONG cRght;
  186. ULONG iLeft;
  187. ULONG iRght;
  188. ULONG ulLeft;
  189. ULONG ulRght;
  190. ULONG yPat;
  191. LONG yTrg;
  192. LONG xLeft;
  193. LONG yTop;
  194. BOOL bSimple = FALSE;
  195. cLeft = ((RECTL *) ppbf->pvObj)->left * ppbf->cMul;
  196. cRght = ((RECTL *) ppbf->pvObj)->right * ppbf->cMul;
  197. iLeft = cLeft & 3;
  198. iRght = cRght & 3;
  199. ulLeft = aulLeftMask[iLeft];
  200. ulRght = ~aulLeftMask[iRght];
  201. cLeft &= ~3; // Align to DWORD
  202. cRght &= ~3; // Align to DWORD
  203. // Compute the correct starting point in the pattern:
  204. xLeft = cLeft - ppbf->xPat;
  205. if (xLeft < 0)
  206. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  207. else xLeft %= ppbf->cxPat;
  208. yTop = ((RECTL *) ppbf->pvObj)->top - ppbf->yPat;
  209. if (yTop < 0)
  210. yTop = (ppbf->cyPat-1) - ((-yTop-1) % ppbf->cyPat);
  211. else yTop %= ppbf->cyPat;
  212. // If these are the same DWORD, then only one strip will be needed.
  213. // Merge the two masks together and just do the left edge.
  214. if (cLeft == cRght)
  215. {
  216. ulLeft &= ulRght;
  217. bSimple = TRUE;
  218. }
  219. // Lay down left edge, if needed.
  220. if (bSimple || (iLeft != 0))
  221. {
  222. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  223. yPat = yTop;
  224. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  225. ff.xPat = xLeft;
  226. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  227. {
  228. *pulTrg = (*pulTrg & ~ulLeft) | (~FETCHMISALIGNED(&ff) & ulLeft);
  229. yPat++;
  230. ASSERTGDI(yPat<=ppbf->cyPat, "vPatNotRect8: Reading past the end of the pattern.\n");
  231. if (yPat == ppbf->cyPat)
  232. {
  233. ff.pvPat = ppbf->pvPat;
  234. yPat = 0;
  235. }
  236. else
  237. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  238. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  239. }
  240. if (bSimple)
  241. return;
  242. cLeft += sizeof(DWORD); // Move to next DWORD
  243. xLeft += sizeof(DWORD); // Move to next DWORD
  244. }
  245. ff.culFill = (cRght - cLeft) >> 2;
  246. // Lay down center stripe, if needed.
  247. if (ff.culFill != 0)
  248. {
  249. yPat = yTop;
  250. xLeft %= ppbf->cxPat;
  251. ff.pvTrg = (PVOID) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  252. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  253. ff.cxPat = ppbf->cxPat;
  254. ff.xPat = xLeft;
  255. ff.culWidth = ppbf->cxPat;
  256. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  257. {
  258. ff.culWidth >>= 2;
  259. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  260. {
  261. vFetchNotAndCopy(&ff);
  262. yPat++;
  263. ASSERTGDI(yPat<=ppbf->cyPat, "vPatNotRect8: Reading past the end of the pattern.\n");
  264. if (yPat == ppbf->cyPat)
  265. {
  266. ff.pvPat = ppbf->pvPat;
  267. yPat = 0;
  268. }
  269. else
  270. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  271. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  272. }
  273. }
  274. else
  275. {
  276. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  277. {
  278. vFetchShiftNotAndCopy(&ff);
  279. yPat++;
  280. ASSERTGDI(yPat<=ppbf->cyPat, "vPatNotRect8: Reading past the end of the pattern.\n");
  281. if (yPat == ppbf->cyPat)
  282. {
  283. ff.pvPat = ppbf->pvPat;
  284. yPat = 0;
  285. }
  286. else
  287. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  288. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  289. ff.xPat = xLeft; // vFetchShift nukes this
  290. }
  291. }
  292. }
  293. // Lay down right edge, if needed.
  294. if (iRght != 0)
  295. {
  296. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cRght);
  297. yPat = yTop;
  298. xLeft += (ff.culFill * sizeof(DWORD));
  299. xLeft %= ppbf->cxPat;
  300. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  301. ff.xPat = xLeft;
  302. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  303. {
  304. *pulTrg = (*pulTrg & ~ulRght) | (~FETCHMISALIGNED(&ff) & ulRght);
  305. yPat++;
  306. ASSERTGDI(yPat<=ppbf->cyPat, "vPatNotRect8: Reading past the end of the pattern.\n");
  307. if (yPat == ppbf->cyPat)
  308. {
  309. ff.pvPat = ppbf->pvPat;
  310. yPat = 0;
  311. }
  312. else
  313. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  314. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  315. }
  316. }
  317. }
  318. /******************************Public*Routine******************************\
  319. * vPatXorRect8
  320. *
  321. * Tiles a pattern to 8/16/24 and 32 bpp bitmaps
  322. *
  323. * History:
  324. * 25-Jan-1992 -by- Donald Sidoroff [donalds]
  325. * Wrote it.
  326. \**************************************************************************/
  327. VOID vPatXorRect8(PATBLTFRAME *ppbf)
  328. {
  329. FETCHFRAME ff;
  330. ULONG *pulTrg;
  331. ULONG cLeft;
  332. ULONG cRght;
  333. ULONG iLeft;
  334. ULONG iRght;
  335. ULONG ulLeft;
  336. ULONG ulRght;
  337. ULONG yPat;
  338. LONG yTrg;
  339. LONG xLeft;
  340. LONG yTop;
  341. BOOL bSimple = FALSE;
  342. cLeft = ((RECTL *) ppbf->pvObj)->left * ppbf->cMul;
  343. cRght = ((RECTL *) ppbf->pvObj)->right * ppbf->cMul;
  344. iLeft = cLeft & 3;
  345. iRght = cRght & 3;
  346. ulLeft = aulLeftMask[iLeft];
  347. ulRght = ~aulLeftMask[iRght];
  348. cLeft &= ~3; // Align to DWORD
  349. cRght &= ~3; // Align to DWORD
  350. // Compute the correct starting point in the pattern:
  351. xLeft = cLeft - ppbf->xPat;
  352. if (xLeft < 0)
  353. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  354. else xLeft %= ppbf->cxPat;
  355. yTop = ((RECTL *) ppbf->pvObj)->top - ppbf->yPat;
  356. if (yTop < 0)
  357. yTop = (ppbf->cyPat-1) - ((-yTop-1) % ppbf->cyPat);
  358. else yTop %= ppbf->cyPat;
  359. // If these are the same DWORD, then only one strip will be needed.
  360. // Merge the two masks together and just do the left edge.
  361. if (cLeft == cRght)
  362. {
  363. ulLeft &= ulRght;
  364. bSimple = TRUE;
  365. }
  366. // Lay down left edge, if needed.
  367. if (bSimple || (iLeft != 0))
  368. {
  369. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  370. yPat = yTop;
  371. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  372. ff.xPat = xLeft;
  373. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  374. {
  375. *pulTrg ^= (FETCHMISALIGNED(&ff) & ulLeft);
  376. yPat++;
  377. ASSERTGDI(yPat<=ppbf->cyPat, "vPatXorRect8: Reading past the end of the pattern.\n");
  378. if (yPat == ppbf->cyPat)
  379. {
  380. ff.pvPat = ppbf->pvPat;
  381. yPat = 0;
  382. }
  383. else
  384. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  385. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  386. }
  387. if (bSimple)
  388. return;
  389. cLeft += sizeof(DWORD); // Move to next DWORD
  390. xLeft += sizeof(DWORD); // Move to next DWORD
  391. }
  392. ff.culFill = (cRght - cLeft) >> 2;
  393. // Lay down center stripe, if needed.
  394. if (ff.culFill != 0)
  395. {
  396. yPat = yTop;
  397. xLeft %= ppbf->cxPat;
  398. ff.pvTrg = (PVOID) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cLeft);
  399. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  400. ff.cxPat = ppbf->cxPat;
  401. ff.xPat = xLeft;
  402. ff.culWidth = ppbf->cxPat;
  403. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  404. {
  405. ff.culWidth >>= 2;
  406. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  407. {
  408. vFetchAndMerge(&ff);
  409. yPat++;
  410. ASSERTGDI(yPat<=ppbf->cyPat, "vPatXorRect8: Reading past the end of the pattern.\n");
  411. if (yPat == ppbf->cyPat)
  412. {
  413. ff.pvPat = ppbf->pvPat;
  414. yPat = 0;
  415. }
  416. else
  417. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  418. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  419. }
  420. }
  421. else
  422. {
  423. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  424. {
  425. vFetchShiftAndMerge(&ff);
  426. yPat++;
  427. ASSERTGDI(yPat<=ppbf->cyPat, "vPatXorRect8: Reading past the end of the pattern.\n");
  428. if (yPat == ppbf->cyPat)
  429. {
  430. ff.pvPat = ppbf->pvPat;
  431. yPat = 0;
  432. }
  433. else
  434. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  435. ff.pvTrg = (PVOID) ((BYTE *) ff.pvTrg + ppbf->lDeltaTrg);
  436. ff.xPat = xLeft; // vFetchShift nukes this
  437. }
  438. }
  439. }
  440. // Lay down right edge, if needed.
  441. if (iRght != 0)
  442. {
  443. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * ((RECTL *) ppbf->pvObj)->top + cRght);
  444. yPat = yTop;
  445. xLeft += (ff.culFill * sizeof(DWORD));
  446. xLeft %= ppbf->cxPat;
  447. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yTop);
  448. ff.xPat = xLeft;
  449. for (yTrg = ((RECTL *) ppbf->pvObj)->top; yTrg < ((RECTL *) ppbf->pvObj)->bottom; yTrg++)
  450. {
  451. *pulTrg ^= (FETCHMISALIGNED(&ff) & ulRght);
  452. yPat++;
  453. ASSERTGDI(yPat<=ppbf->cyPat, "vPatXorRect8: Reading past the end of the pattern.\n");
  454. if (yPat == ppbf->cyPat)
  455. {
  456. ff.pvPat = ppbf->pvPat;
  457. yPat = 0;
  458. }
  459. else
  460. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  461. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  462. }
  463. }
  464. }
  465. /******************************Public*Routine******************************\
  466. * vPatCpyRow8
  467. *
  468. * Tiles a pattern to 8/16/24 and 32 bpp bitmaps
  469. *
  470. * History:
  471. * 08-Mar-1992 -by- Donald Sidoroff [donalds]
  472. * Wrote it.
  473. \**************************************************************************/
  474. VOID vPatCpyRow8(
  475. PATBLTFRAME *ppbf,
  476. LONG yStart,
  477. INT crow)
  478. {
  479. FETCHFRAME ff;
  480. ULONG *pulTrg;
  481. ULONG *pulTmp;
  482. ULONG cLeft;
  483. ULONG cRght;
  484. ULONG iLeft;
  485. ULONG iRght;
  486. ULONG ulLeft;
  487. ULONG ulRght;
  488. LONG yPat;
  489. LONG xLeft;
  490. PROW prow = (PROW) ppbf->pvObj;
  491. // Initialize the DDA
  492. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * yStart);
  493. // Compute the correct y starting point in the pattern:
  494. yPat = yStart - ppbf->yPat;
  495. if (yPat < 0)
  496. yPat = (ppbf->cyPat-1) - ((-yPat-1) % ppbf->cyPat);
  497. else yPat %= ppbf->cyPat;
  498. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yPat);
  499. for (; crow; crow--, prow++)
  500. {
  501. cLeft = prow->left * ppbf->cMul;
  502. cRght = prow->right * ppbf->cMul;
  503. iLeft = cLeft & 3;
  504. iRght = cRght & 3;
  505. ulLeft = aulLeftMask[iLeft];
  506. ulRght = ~aulLeftMask[iRght];
  507. cLeft &= ~3; // Align to DWORD
  508. cRght &= ~3; // Align to DWORD
  509. // Calculate the correct x starting point in the pattern:
  510. xLeft = cLeft - ppbf->xPat;
  511. if (xLeft < 0)
  512. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  513. else xLeft %= ppbf->cxPat;
  514. if (cLeft == cRght)
  515. {
  516. ulLeft &= ulRght;
  517. ff.xPat = xLeft;
  518. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  519. *pulTmp = (*pulTmp & ~ulLeft) | (FETCHMISALIGNED(&ff) & ulLeft);
  520. }
  521. else
  522. {
  523. // Lay down left side, if needed.
  524. if (iLeft != 0)
  525. {
  526. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  527. ff.xPat = xLeft;
  528. *pulTmp = (*pulTmp & ~ulLeft) | (FETCHMISALIGNED(&ff) & ulLeft);
  529. cLeft += sizeof(DWORD); // Move to next DWORD
  530. xLeft += sizeof(DWORD); // Move to next DWORD
  531. }
  532. // Lay down center, if needed.
  533. ff.culFill = (cRght - cLeft) >> 2;
  534. if (ff.culFill != 0)
  535. {
  536. xLeft %= ppbf->cxPat;
  537. ff.pvTrg = (PVOID) ((BYTE *) pulTrg + cLeft);
  538. ff.cxPat = ppbf->cxPat;
  539. ff.xPat = xLeft;
  540. ff.culWidth = ppbf->cxPat;
  541. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  542. {
  543. ff.culWidth >>= 2;
  544. vFetchAndCopy(&ff);
  545. }
  546. else
  547. vFetchShiftAndCopy(&ff);
  548. }
  549. // Lay down right side, if needed.
  550. if (iRght != 0)
  551. {
  552. pulTmp = (ULONG *) ((BYTE *) pulTrg + cRght);
  553. ff.xPat = (xLeft + (ff.culFill * sizeof(DWORD))) % ppbf->cxPat;
  554. *pulTmp = (*pulTmp & ~ulRght) | (FETCHMISALIGNED(&ff) & ulRght);
  555. }
  556. }
  557. yPat++;
  558. ASSERTGDI(yPat<=(LONG)ppbf->cyPat, "vPatCpyRow8: Reading past the end of the pattern.\n");
  559. if (yPat == (LONG) ppbf->cyPat)
  560. {
  561. ff.pvPat = ppbf->pvPat;
  562. yPat = 0;
  563. }
  564. else
  565. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  566. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  567. }
  568. }
  569. /******************************Public*Routine******************************\
  570. * vPatNotRow8
  571. *
  572. * Tiles the NOT of a pattern to 8/16/24 and 32 bpp bitmaps
  573. *
  574. * History:
  575. * 12-Oct-1993 -by- Eric Kutter [erick]
  576. * converted from traps to rows
  577. *
  578. * 08-Mar-1992 -by- Donald Sidoroff [donalds]
  579. * Wrote it.
  580. \**************************************************************************/
  581. VOID vPatNotRow8(
  582. PATBLTFRAME *ppbf,
  583. LONG yStart,
  584. INT crow)
  585. {
  586. FETCHFRAME ff;
  587. ULONG *pulTrg;
  588. ULONG *pulTmp;
  589. ULONG cLeft;
  590. ULONG cRght;
  591. ULONG iLeft;
  592. ULONG iRght;
  593. ULONG ulLeft;
  594. ULONG ulRght;
  595. LONG yPat;
  596. LONG xLeft;
  597. PROW prow = (PROW) ppbf->pvObj;
  598. // Initialize the DDA
  599. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * yStart);
  600. // Compute the correct y starting point in the pattern:
  601. yPat = yStart - ppbf->yPat;
  602. if (yPat < 0)
  603. yPat = (ppbf->cyPat-1) - ((-yPat-1) % ppbf->cyPat);
  604. else yPat %= ppbf->cyPat;
  605. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yPat);
  606. for (; crow; crow--, prow++)
  607. {
  608. cLeft = prow->left * ppbf->cMul;
  609. cRght = prow->right * ppbf->cMul;
  610. iLeft = cLeft & 3;
  611. iRght = cRght & 3;
  612. ulLeft = aulLeftMask[iLeft];
  613. ulRght = ~aulLeftMask[iRght];
  614. cLeft &= ~3; // Align to DWORD
  615. cRght &= ~3; // Align to DWORD
  616. // Calculate the correct x starting point in the pattern:
  617. xLeft = cLeft - ppbf->xPat;
  618. if (xLeft < 0)
  619. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  620. else xLeft %= ppbf->cxPat;
  621. if (cLeft == cRght)
  622. {
  623. ulLeft &= ulRght;
  624. ff.xPat = xLeft;
  625. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  626. *pulTmp = (*pulTmp & ~ulLeft) | (FETCHMISALIGNED(&ff) & ulLeft);
  627. }
  628. else
  629. {
  630. // Lay down left side, if needed.
  631. if (iLeft != 0)
  632. {
  633. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  634. ff.xPat = xLeft;
  635. *pulTmp = (*pulTmp & ~ulLeft) | (~FETCHMISALIGNED(&ff) & ulLeft);
  636. cLeft += sizeof(DWORD); // Move to next DWORD
  637. xLeft += sizeof(DWORD); // Move to next DWORD
  638. }
  639. // Lay down center, if needed.
  640. ff.culFill = (cRght - cLeft) >> 2;
  641. if (ff.culFill != 0)
  642. {
  643. xLeft %= ppbf->cxPat;
  644. ff.pvTrg = (PVOID) ((BYTE *) pulTrg + cLeft);
  645. ff.cxPat = ppbf->cxPat;
  646. ff.xPat = xLeft;
  647. ff.culWidth = ppbf->cxPat;
  648. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  649. {
  650. ff.culWidth >>= 2;
  651. vFetchNotAndCopy(&ff);
  652. }
  653. else
  654. vFetchShiftNotAndCopy(&ff);
  655. }
  656. // Lay down right side, if needed.
  657. if (iRght != 0)
  658. {
  659. pulTmp = (ULONG *) ((BYTE *) pulTrg + cRght);
  660. ff.xPat = (xLeft + (ff.culFill * sizeof(DWORD))) % ppbf->cxPat;
  661. *pulTmp = (*pulTmp & ~ulRght) | (~FETCHMISALIGNED(&ff) & ulRght);
  662. }
  663. }
  664. yPat++;
  665. ASSERTGDI(yPat<=(LONG)ppbf->cyPat, "vPatNotRow8: Reading past the end of the pattern.\n");
  666. if (yPat == (LONG) ppbf->cyPat)
  667. {
  668. ff.pvPat = ppbf->pvPat;
  669. yPat = 0;
  670. }
  671. else
  672. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  673. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  674. }
  675. }
  676. /******************************Public*Routine******************************\
  677. * vPatXorRow8
  678. *
  679. * XOR Tiles a pattern to 8/16/24 and 32 bpp bitmaps
  680. *
  681. * History:
  682. * 12-Oct-1993 -by- Eric Kutter [erick]
  683. * Converted from traps to rows
  684. *
  685. * 08-Mar-1992 -by- Donald Sidoroff [donalds]
  686. * Wrote it.
  687. \**************************************************************************/
  688. VOID vPatXorRow8(
  689. PATBLTFRAME *ppbf,
  690. LONG yStart,
  691. INT crow)
  692. {
  693. FETCHFRAME ff;
  694. ULONG *pulTrg;
  695. ULONG *pulTmp;
  696. ULONG cLeft;
  697. ULONG cRght;
  698. ULONG iLeft;
  699. ULONG iRght;
  700. ULONG ulLeft;
  701. ULONG ulRght;
  702. LONG yPat;
  703. LONG xLeft;
  704. PROW prow = (PROW) ppbf->pvObj;
  705. // Initialize the DDA
  706. pulTrg = (ULONG *) (((BYTE *) ppbf->pvTrg) + ppbf->lDeltaTrg * yStart);
  707. // Compute the correct y starting point in the pattern:
  708. yPat = yStart - ppbf->yPat;
  709. if (yPat < 0)
  710. yPat = (ppbf->cyPat-1) - ((-yPat-1) % ppbf->cyPat);
  711. else yPat %= ppbf->cyPat;
  712. ff.pvPat = (PVOID) (((BYTE *) ppbf->pvPat) + ppbf->lDeltaPat * yPat);
  713. for (; crow; crow--, prow++)
  714. {
  715. cLeft = prow->left * ppbf->cMul;
  716. cRght = prow->right * ppbf->cMul;
  717. iLeft = cLeft & 3;
  718. iRght = cRght & 3;
  719. ulLeft = aulLeftMask[iLeft];
  720. ulRght = ~aulLeftMask[iRght];
  721. cLeft &= ~3; // Align to DWORD
  722. cRght &= ~3; // Align to DWORD
  723. // Calculate the correct x starting point in the pattern:
  724. xLeft = cLeft - ppbf->xPat;
  725. if (xLeft < 0)
  726. xLeft = (ppbf->cxPat-1) - ((-xLeft-1) % ppbf->cxPat);
  727. else xLeft %= ppbf->cxPat;
  728. if (cLeft == cRght)
  729. {
  730. ulLeft &= ulRght;
  731. ff.xPat = xLeft;
  732. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  733. *pulTmp ^= (FETCHMISALIGNED(&ff) & ulLeft);
  734. }
  735. else
  736. {
  737. // Lay down left side, if needed.
  738. if (iLeft != 0)
  739. {
  740. pulTmp = (ULONG *) ((BYTE *) pulTrg + cLeft);
  741. ff.xPat = xLeft;
  742. *pulTmp ^= (FETCHMISALIGNED(&ff) & ulLeft);
  743. cLeft += sizeof(DWORD); // Move to next DWORD
  744. xLeft += sizeof(DWORD); // Move to next DWORD
  745. }
  746. // Lay down center, if needed.
  747. ff.culFill = (cRght - cLeft) >> 2;
  748. if (ff.culFill != 0)
  749. {
  750. xLeft %= ppbf->cxPat;
  751. ff.pvTrg = (PVOID) ((BYTE *) pulTrg + cLeft);
  752. ff.cxPat = ppbf->cxPat;
  753. ff.xPat = xLeft;
  754. ff.culWidth = ppbf->cxPat;
  755. if (((xLeft & 3) == 0) && ((ff.culWidth & 3) == 0))
  756. {
  757. ff.culWidth >>= 2;
  758. vFetchAndMerge(&ff);
  759. }
  760. else
  761. vFetchShiftAndMerge(&ff);
  762. }
  763. // Lay down right side, if needed.
  764. if (iRght != 0)
  765. {
  766. pulTmp = (ULONG *) ((BYTE *) pulTrg + cRght);
  767. ff.xPat = (xLeft + (ff.culFill * sizeof(DWORD))) % ppbf->cxPat;
  768. *pulTmp ^= (FETCHMISALIGNED(&ff) & ulRght);
  769. }
  770. }
  771. yPat++;
  772. ASSERTGDI(yPat<=(LONG)ppbf->cyPat, "vPatXorRow8: Reading past the end of the pattern.\n");
  773. if (yPat == (LONG) ppbf->cyPat)
  774. {
  775. ff.pvPat = ppbf->pvPat;
  776. yPat = 0;
  777. }
  778. else
  779. ff.pvPat = (PVOID) ((BYTE *) ff.pvPat + ppbf->lDeltaPat);
  780. pulTrg = (ULONG *) (((BYTE *) pulTrg) + ppbf->lDeltaTrg);
  781. }
  782. }
  783. /******************************Public*Routine******************************\
  784. * vPatternCopyLoopRow
  785. *
  786. * This is the inner loop of the 1 bpp and 4 bpp bitmap SrcCpy PatBlt-ing
  787. * routines, this is were we finally write the DWORDs to the bitmap.
  788. *
  789. * History:
  790. * 12-Oct-1993 -by- Eric Kutter [erick]
  791. * Converted from rects to rows
  792. *
  793. * 19-2-93 checker
  794. * ported stephene's stuff
  795. \**************************************************************************/
  796. VOID vPatternCopyLoopRow(LONG lCurYTop, ULONG *pulTrg, PATBLTFRAME *ppbf,
  797. int ulFillType, ULONG ulRightPatMask, ULONG ulLeftPatMask,
  798. ULONG ulRightDestMask, ULONG ulLeftDestMask, LONG lMiddleDwords,
  799. PULONG pulBasePat)
  800. {
  801. ULONG *pulPatPtr;
  802. LONG lMiddleBytes;
  803. ULONG ulPattern;
  804. ULONG ulRightDestMaskedPattern;
  805. ULONG ulLeftDestMaskedPattern;
  806. lMiddleBytes = lMiddleDwords << 2;
  807. pulPatPtr = pulBasePat + ((lCurYTop - ppbf->yPat) & 0x07);
  808. // Set up the appropriately rotated version of the current pattern scan
  809. ulPattern = *pulPatPtr;
  810. // Draw all Y scans for this pattern byte
  811. switch(ulFillType)
  812. {
  813. case LEFT_MIDDLE_RIGHT:
  814. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  815. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  816. *pulTrg = (*pulTrg & ulLeftDestMask) |
  817. ulLeftDestMaskedPattern;
  818. RtlFillMemoryUlong (pulTrg+1, lMiddleBytes, ulPattern);
  819. *(pulTrg+lMiddleDwords+1) =
  820. (*(pulTrg+lMiddleDwords+1) & ulRightDestMask) |
  821. ulRightDestMaskedPattern;
  822. break;
  823. case LEFT_MIDDLE:
  824. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  825. *pulTrg = (*pulTrg & ulLeftDestMask) |
  826. ulLeftDestMaskedPattern;
  827. RtlFillMemoryUlong (pulTrg+1, lMiddleBytes, ulPattern);
  828. break;
  829. case MIDDLE_RIGHT:
  830. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  831. RtlFillMemoryUlong (pulTrg, lMiddleBytes, ulPattern);
  832. *(pulTrg+lMiddleDwords) =
  833. (*(pulTrg+lMiddleDwords) & ulRightDestMask) |
  834. ulRightDestMaskedPattern;
  835. break;
  836. case MIDDLE:
  837. RtlFillMemoryUlong (pulTrg, lMiddleBytes, ulPattern);
  838. break;
  839. case LEFT_MIDDLE_RIGHT_SHORT:
  840. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  841. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  842. *pulTrg = (*pulTrg & ulLeftDestMask) |
  843. ulLeftDestMaskedPattern;
  844. switch(lMiddleDwords)
  845. {
  846. case 9:
  847. *(pulTrg+9) = ulPattern;
  848. case 8:
  849. *(pulTrg+8) = ulPattern;
  850. case 7:
  851. *(pulTrg+7) = ulPattern;
  852. case 6:
  853. *(pulTrg+6) = ulPattern;
  854. case 5:
  855. *(pulTrg+5) = ulPattern;
  856. case 4:
  857. *(pulTrg+4) = ulPattern;
  858. case 3:
  859. *(pulTrg+3) = ulPattern;
  860. case 2:
  861. *(pulTrg+2) = ulPattern;
  862. case 1:
  863. *(pulTrg+1) = ulPattern;
  864. break;
  865. }
  866. *(pulTrg+lMiddleDwords+1) =
  867. (*(pulTrg+lMiddleDwords+1) & ulRightDestMask) |
  868. ulRightDestMaskedPattern;
  869. break;
  870. case LEFT_MIDDLE_SHORT:
  871. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  872. *pulTrg = (*pulTrg & ulLeftDestMask) |
  873. ulLeftDestMaskedPattern;
  874. switch(lMiddleDwords)
  875. {
  876. case 9:
  877. *(pulTrg+9) = ulPattern;
  878. case 8:
  879. *(pulTrg+8) = ulPattern;
  880. case 7:
  881. *(pulTrg+7) = ulPattern;
  882. case 6:
  883. *(pulTrg+6) = ulPattern;
  884. case 5:
  885. *(pulTrg+5) = ulPattern;
  886. case 4:
  887. *(pulTrg+4) = ulPattern;
  888. case 3:
  889. *(pulTrg+3) = ulPattern;
  890. case 2:
  891. *(pulTrg+2) = ulPattern;
  892. case 1:
  893. *(pulTrg+1) = ulPattern;
  894. break;
  895. }
  896. break;
  897. case MIDDLE_RIGHT_SHORT:
  898. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  899. switch(lMiddleDwords)
  900. {
  901. case 9:
  902. *(pulTrg+8) = ulPattern;
  903. case 8:
  904. *(pulTrg+7) = ulPattern;
  905. case 7:
  906. *(pulTrg+6) = ulPattern;
  907. case 6:
  908. *(pulTrg+5) = ulPattern;
  909. case 5:
  910. *(pulTrg+4) = ulPattern;
  911. case 4:
  912. *(pulTrg+3) = ulPattern;
  913. case 3:
  914. *(pulTrg+2) = ulPattern;
  915. case 2:
  916. *(pulTrg+1) = ulPattern;
  917. case 1:
  918. *(pulTrg) = ulPattern;
  919. break;
  920. }
  921. *(pulTrg+lMiddleDwords) =
  922. (*(pulTrg+lMiddleDwords) & ulRightDestMask) |
  923. ulRightDestMaskedPattern;
  924. break;
  925. case MIDDLE_SHORT:
  926. switch(lMiddleDwords)
  927. {
  928. case 9:
  929. *(pulTrg+8) = ulPattern;
  930. case 8:
  931. *(pulTrg+7) = ulPattern;
  932. case 7:
  933. *(pulTrg+6) = ulPattern;
  934. case 6:
  935. *(pulTrg+5) = ulPattern;
  936. case 5:
  937. *(pulTrg+4) = ulPattern;
  938. case 4:
  939. *(pulTrg+3) = ulPattern;
  940. case 3:
  941. *(pulTrg+2) = ulPattern;
  942. case 2:
  943. *(pulTrg+1) = ulPattern;
  944. case 1:
  945. *(pulTrg) = ulPattern;
  946. break;
  947. }
  948. break;
  949. case LEFT_RIGHT:
  950. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  951. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  952. *pulTrg = (*pulTrg & ulLeftDestMask) |
  953. ulLeftDestMaskedPattern;
  954. *(pulTrg+1) = (*(pulTrg+1) & ulRightDestMask) |
  955. ulRightDestMaskedPattern;
  956. break;
  957. case LEFT:
  958. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  959. *pulTrg = (*pulTrg & ulLeftDestMask) |
  960. ulLeftDestMaskedPattern;
  961. break;
  962. }
  963. }
  964. /******************************Public*Routine******************************\
  965. * vPatCpyRow4_8x8
  966. *
  967. * Tiles an 8x8 pattern to 4 bpp bitmaps, for SRCCOPY rasterop only.
  968. * Fills however many rectangles are specified by crcl
  969. * Assumes pattern bytes are contiguous (lDelta for pattern is 4).
  970. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-7.
  971. * Assumes there is at least one rectangle to fill.
  972. *
  973. * History:
  974. * 07-Nov-1992 -by- Michael Abrash [mikeab]
  975. * Wrote it.
  976. \**************************************************************************/
  977. VOID vPatCpyRow4_8x8(PATBLTFRAME *ppbf, LONG yStart, INT crow)
  978. {
  979. PULONG pulTrgBase;
  980. LONG lMiddleDwords;
  981. LONG lMiddleBytes;
  982. int ulFillType;
  983. ULONG ulLeftDestMask;
  984. ULONG ulRightDestMask;
  985. ULONG ulLeftPatMask;
  986. ULONG ulRightPatMask;
  987. UCHAR ucPatRotateRight;
  988. UCHAR ucPatRotateLeft;
  989. ULONG ulTemp;
  990. ULONG *pulPatMax;
  991. ULONG *pulBasePat;
  992. ULONG *pulTempSrc;
  993. ULONG *pulTempDst;
  994. ULONG ulAlignedPat[8]; // temp storage for rotated pattern
  995. static ULONG aulMask[8] = { 0, 0x000000F0, 0x000000FF, 0x0000F0FF,
  996. 0x0000FFFF, 0x00F0FFFF, 0x00FFFFFF, 0xF0FFFFFF};
  997. // Point to list of rectangles to fill
  998. PROW prow = (PROW) ppbf->pvObj;
  999. // Rotate the pattern if needed, storing in a temp buffer. This way we only
  1000. // rotate once, no matter how many fills we perform per call
  1001. if (ppbf->xPat == 0)
  1002. {
  1003. pulBasePat = (ULONG *)ppbf->pvPat; // no rotation; that's easy
  1004. // Remember where the pattern ends, for wrapping
  1005. pulPatMax = pulBasePat + 8;
  1006. }
  1007. else
  1008. {
  1009. // Set up the shifts to produce the rotation effect to align the pattern
  1010. // as specified (the results of the two shifts are ORed together to emulate
  1011. // the rotate, because C can't do rotations directly)
  1012. ucPatRotateRight = (UCHAR) ppbf->xPat << 2;
  1013. ucPatRotateLeft = (sizeof(ULONG) * 8) - ucPatRotateRight;
  1014. pulTempSrc = (ULONG *)ppbf->pvPat;
  1015. pulTempDst = ulAlignedPat;
  1016. pulBasePat = pulTempDst;
  1017. // Remember where the pattern ends, for wrapping
  1018. pulPatMax = pulBasePat + 8;
  1019. while (pulTempDst < pulPatMax)
  1020. {
  1021. // Go through this mess to convert to big endian, so we can rotate
  1022. *(((UCHAR *)&ulTemp) + 3) = *(((UCHAR *)pulTempSrc) + 0);
  1023. *(((UCHAR *)&ulTemp) + 2) = *(((UCHAR *)pulTempSrc) + 1);
  1024. *(((UCHAR *)&ulTemp) + 1) = *(((UCHAR *)pulTempSrc) + 2);
  1025. *(((UCHAR *)&ulTemp) + 0) = *(((UCHAR *)pulTempSrc) + 3);
  1026. // Rotate the pattern into position
  1027. ulTemp = (ulTemp >> ucPatRotateRight) |
  1028. (ulTemp << ucPatRotateLeft);
  1029. // Convert back to little endian, so we can store the pattern for
  1030. // use in drawing
  1031. *(((UCHAR *)pulTempDst) + 3) = *(((UCHAR *)&ulTemp) + 0);
  1032. *(((UCHAR *)pulTempDst) + 2) = *(((UCHAR *)&ulTemp) + 1);
  1033. *(((UCHAR *)pulTempDst) + 1) = *(((UCHAR *)&ulTemp) + 2);
  1034. *(((UCHAR *)pulTempDst) + 0) = *(((UCHAR *)&ulTemp) + 3);
  1035. pulTempSrc++;
  1036. pulTempDst++;
  1037. }
  1038. }
  1039. // advance to the first scan
  1040. PBYTE pjBase = (BYTE *) ppbf->pvTrg + (ppbf->lDeltaTrg * yStart);
  1041. // Loop through all rectangles to fill
  1042. do
  1043. {
  1044. // Set up AND/OR masks for partial-dword edges, for masking both the
  1045. // pattern dword and the destination dword (the pattern and destination
  1046. // masks are complementary). A solid dword is 0 for dest, -1 for pattern
  1047. ulLeftDestMask = aulMask[prow->left & 0x07];
  1048. ulLeftPatMask = ~ulLeftDestMask;
  1049. if ((ulRightPatMask = aulMask[prow->right & 0x07]) == 0)
  1050. {
  1051. ulRightPatMask = 0xFFFFFFFF; // force solid to -1 for pattern
  1052. }
  1053. ulRightDestMask = ~ulRightPatMask;
  1054. // Point to the first dword to fill
  1055. pulTrgBase = (ULONG *) (pjBase + ((prow->left >> 1) & ~3));
  1056. // Number of whole middle dwords/bytes to fill a dword at a time
  1057. lMiddleDwords = (((LONG)(prow->right >> 1) & ~0x03) -
  1058. (((LONG)(prow->left + 7) >> 1) & ~0x03)) >> 2;
  1059. lMiddleBytes = lMiddleDwords << 2;
  1060. // Set up for the appropriate fill, given partial dwords at edges and
  1061. // narrow cases
  1062. switch (lMiddleDwords + 1)
  1063. {
  1064. case 1: // left and right, but no middle, or
  1065. // possibly just one, partial, dword
  1066. if ((ulLeftDestMask != 0) && (ulRightDestMask != 0)) {
  1067. // Left and right, but no middle
  1068. ulFillType = LEFT_RIGHT;
  1069. break;
  1070. }
  1071. // Note fallthrough in case where one of the masks is 0, meaning we
  1072. // have a single, partial dword
  1073. case 0: // just one, partial, dword, which
  1074. // we'll treat as a left edge
  1075. ulFillType = LEFT;
  1076. ulLeftPatMask &= ulRightPatMask;
  1077. ulLeftDestMask = ~ulLeftPatMask;
  1078. break;
  1079. case 2: // special case narrow cases, to avoid RTL
  1080. case 3: // call overhead and REP STOSD startup overhead
  1081. case 4:
  1082. case 5:
  1083. case 6:
  1084. case 7:
  1085. case 8:
  1086. case 9:
  1087. case 10:
  1088. if (ulLeftDestMask == 0)
  1089. {
  1090. if (ulRightDestMask == 0)
  1091. {
  1092. ulFillType = MIDDLE_SHORT;
  1093. }
  1094. else
  1095. {
  1096. ulFillType = MIDDLE_RIGHT_SHORT;
  1097. }
  1098. }
  1099. else
  1100. {
  1101. if (ulRightDestMask == 0)
  1102. {
  1103. ulFillType = LEFT_MIDDLE_SHORT;
  1104. }
  1105. else
  1106. {
  1107. ulFillType = LEFT_MIDDLE_RIGHT_SHORT;
  1108. }
  1109. }
  1110. break;
  1111. default:
  1112. if (ulLeftDestMask == 0)
  1113. {
  1114. if (ulRightDestMask == 0)
  1115. {
  1116. ulFillType = MIDDLE;
  1117. }
  1118. else
  1119. {
  1120. ulFillType = MIDDLE_RIGHT;
  1121. }
  1122. }
  1123. else
  1124. {
  1125. if (ulRightDestMask == 0)
  1126. {
  1127. ulFillType = LEFT_MIDDLE;
  1128. }
  1129. else
  1130. {
  1131. ulFillType = LEFT_MIDDLE_RIGHT;
  1132. }
  1133. }
  1134. break;
  1135. }
  1136. vPatternCopyLoopRow(yStart,pulTrgBase,ppbf,ulFillType,ulRightPatMask,
  1137. ulLeftPatMask,ulRightDestMask,ulLeftDestMask,lMiddleDwords,
  1138. pulBasePat);
  1139. // Point to the next rectangle to fill, if there is one
  1140. prow++;
  1141. yStart++ ;
  1142. pjBase += ppbf->lDeltaTrg;
  1143. }
  1144. while (--crow);
  1145. }
  1146. /******************************Public*Routine******************************\
  1147. * vPatCpyRect4_8x8
  1148. *
  1149. * Tiles an 8x8 pattern to 4 bpp bitmaps, for SRCCOPY rasterop only.
  1150. * Fills however many rectangles are specified by crcl
  1151. * Assumes pattern bytes are contiguous (lDelta for pattern is 4).
  1152. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-7.
  1153. * Assumes there is at least one rectangle to fill.
  1154. *
  1155. * History:
  1156. * 07-Nov-1992 -by- Michael Abrash [mikeab]
  1157. * Wrote it.
  1158. \**************************************************************************/
  1159. VOID vPatCpyRect4_8x8(PATBLTFRAME *ppbf, INT crcl)
  1160. {
  1161. PULONG pulTrgBase;
  1162. PRECTL prcl;
  1163. LONG lDelta;
  1164. LONG lDeltaX8;
  1165. LONG lMiddleDwords;
  1166. LONG lMiddleBytes;
  1167. int ulFillType;
  1168. ULONG ulLeftDestMask;
  1169. ULONG ulRightDestMask;
  1170. ULONG ulLeftPatMask;
  1171. ULONG ulRightPatMask;
  1172. UCHAR ucPatRotateRight;
  1173. UCHAR ucPatRotateLeft;
  1174. ULONG ulTemp;
  1175. ULONG *pulPatMax;
  1176. ULONG *pulBasePat;
  1177. ULONG *pulTempSrc;
  1178. ULONG *pulTempDst;
  1179. ULONG ulAlignedPat[8]; // temp storage for rotated pattern
  1180. static ULONG aulMask[8] = { 0, 0x000000F0, 0x000000FF, 0x0000F0FF,
  1181. 0x0000FFFF, 0x00F0FFFF, 0x00FFFFFF, 0xF0FFFFFF};
  1182. // Point to list of rectangles to fill
  1183. prcl = (RECTL *) ppbf->pvObj;
  1184. // Offset to next scan, offset to every eighth scan
  1185. lDeltaX8 = (lDelta = ppbf->lDeltaTrg) << 3;
  1186. // Rotate the pattern if needed, storing in a temp buffer. This way we only
  1187. // rotate once, no matter how many fills we perform per call
  1188. if (ppbf->xPat == 0)
  1189. {
  1190. pulBasePat = (ULONG *)ppbf->pvPat; // no rotation; that's easy
  1191. // Remember where the pattern ends, for wrapping
  1192. pulPatMax = pulBasePat + 8;
  1193. }
  1194. else
  1195. {
  1196. // Set up the shifts to produce the rotation effect to align the pattern
  1197. // as specified (the results of the two shifts are ORed together to emulate
  1198. // the rotate, because C can't do rotations directly)
  1199. ucPatRotateRight = (UCHAR) ppbf->xPat << 2;
  1200. ucPatRotateLeft = (sizeof(ULONG) * 8) - ucPatRotateRight;
  1201. pulTempSrc = (ULONG *)ppbf->pvPat;
  1202. pulTempDst = ulAlignedPat;
  1203. pulBasePat = pulTempDst;
  1204. // Remember where the pattern ends, for wrapping
  1205. pulPatMax = pulBasePat + 8;
  1206. while (pulTempDst < pulPatMax)
  1207. {
  1208. // Go through this mess to convert to big endian, so we can rotate
  1209. *(((UCHAR *)&ulTemp) + 3) = *(((UCHAR *)pulTempSrc) + 0);
  1210. *(((UCHAR *)&ulTemp) + 2) = *(((UCHAR *)pulTempSrc) + 1);
  1211. *(((UCHAR *)&ulTemp) + 1) = *(((UCHAR *)pulTempSrc) + 2);
  1212. *(((UCHAR *)&ulTemp) + 0) = *(((UCHAR *)pulTempSrc) + 3);
  1213. // Rotate the pattern into position
  1214. ulTemp = (ulTemp >> ucPatRotateRight) |
  1215. (ulTemp << ucPatRotateLeft);
  1216. // Convert back to little endian, so we can store the pattern for
  1217. // use in drawing
  1218. *(((UCHAR *)pulTempDst) + 3) = *(((UCHAR *)&ulTemp) + 0);
  1219. *(((UCHAR *)pulTempDst) + 2) = *(((UCHAR *)&ulTemp) + 1);
  1220. *(((UCHAR *)pulTempDst) + 1) = *(((UCHAR *)&ulTemp) + 2);
  1221. *(((UCHAR *)pulTempDst) + 0) = *(((UCHAR *)&ulTemp) + 3);
  1222. pulTempSrc++;
  1223. pulTempDst++;
  1224. }
  1225. }
  1226. // Loop through all rectangles to fill
  1227. do
  1228. {
  1229. // Set up AND/OR masks for partial-dword edges, for masking both the
  1230. // pattern dword and the destination dword (the pattern and destination
  1231. // masks are complementary). A solid dword is 0 for dest, -1 for pattern
  1232. ulLeftDestMask = aulMask[prcl->left & 0x07];
  1233. ulLeftPatMask = ~ulLeftDestMask;
  1234. if ((ulRightPatMask = aulMask[prcl->right & 0x07]) == 0)
  1235. {
  1236. ulRightPatMask = 0xFFFFFFFF; // force solid to -1 for pattern
  1237. }
  1238. ulRightDestMask = ~ulRightPatMask;
  1239. // Point to the first dword to fill
  1240. pulTrgBase = (ULONG *) (((BYTE *) ppbf->pvTrg) +
  1241. (ppbf->lDeltaTrg * prcl->top) + ((prcl->left >> 1) & ~3));
  1242. // Number of whole middle dwords/bytes to fill a dword at a time
  1243. lMiddleDwords = (((LONG)(prcl->right >> 1) & ~0x03) -
  1244. (((LONG)(prcl->left + 7) >> 1) & ~0x03)) >> 2;
  1245. lMiddleBytes = lMiddleDwords << 2;
  1246. // Set up for the appropriate fill, given partial dwords at edges and
  1247. // narrow cases
  1248. switch (lMiddleDwords + 1)
  1249. {
  1250. case 1: // left and right, but no middle, or
  1251. // possibly just one, partial, dword
  1252. if ((ulLeftDestMask != 0) && (ulRightDestMask != 0)) {
  1253. // Left and right, but no middle
  1254. ulFillType = LEFT_RIGHT;
  1255. break;
  1256. }
  1257. // Note fallthrough in case where one of the masks is 0, meaning we
  1258. // have a single, partial dword
  1259. case 0: // just one, partial, dword, which
  1260. // we'll treat as a left edge
  1261. ulFillType = LEFT;
  1262. ulLeftPatMask &= ulRightPatMask;
  1263. ulLeftDestMask = ~ulLeftPatMask;
  1264. break;
  1265. case 2: // special case narrow cases, to avoid RTL
  1266. case 3: // call overhead and REP STOSD startup overhead
  1267. case 4:
  1268. case 5:
  1269. case 6:
  1270. case 7:
  1271. case 8:
  1272. case 9:
  1273. case 10:
  1274. if (ulLeftDestMask == 0)
  1275. {
  1276. if (ulRightDestMask == 0)
  1277. {
  1278. ulFillType = MIDDLE_SHORT;
  1279. }
  1280. else
  1281. {
  1282. ulFillType = MIDDLE_RIGHT_SHORT;
  1283. }
  1284. }
  1285. else
  1286. {
  1287. if (ulRightDestMask == 0)
  1288. {
  1289. ulFillType = LEFT_MIDDLE_SHORT;
  1290. }
  1291. else
  1292. {
  1293. ulFillType = LEFT_MIDDLE_RIGHT_SHORT;
  1294. }
  1295. }
  1296. break;
  1297. default:
  1298. if (ulLeftDestMask == 0)
  1299. {
  1300. if (ulRightDestMask == 0)
  1301. {
  1302. ulFillType = MIDDLE;
  1303. }
  1304. else
  1305. {
  1306. ulFillType = MIDDLE_RIGHT;
  1307. }
  1308. }
  1309. else
  1310. {
  1311. if (ulRightDestMask == 0)
  1312. {
  1313. ulFillType = LEFT_MIDDLE;
  1314. }
  1315. else
  1316. {
  1317. ulFillType = LEFT_MIDDLE_RIGHT;
  1318. }
  1319. }
  1320. break;
  1321. }
  1322. vPatternCopyLoop(prcl,pulTrgBase,ppbf,ulFillType,ulRightPatMask,
  1323. ulLeftPatMask,ulRightDestMask,ulLeftDestMask,lMiddleDwords,
  1324. lDelta,lDeltaX8,pulBasePat,pulPatMax);
  1325. // Point to the next rectangle to fill, if there is one
  1326. prcl++;
  1327. }
  1328. while (--crcl);
  1329. }
  1330. /******************************Public*Routine******************************\
  1331. * vPatternCopyLoop
  1332. *
  1333. * This is the inner loop of the 1 bpp and 4 bpp bitmap SrcCpy PatBlt-ing
  1334. * routines, this is were we finally write the DWORDs to the bitmap.
  1335. *
  1336. * History:
  1337. * 19-2-93 checker
  1338. * ported stephene's stuff
  1339. \**************************************************************************/
  1340. VOID vPatternCopyLoop( PRECTL prcl, ULONG *pulTrgBase, PATBLTFRAME *ppbf,
  1341. int ulFillType, ULONG ulRightPatMask, ULONG ulLeftPatMask,
  1342. ULONG ulRightDestMask, ULONG ulLeftDestMask, LONG lMiddleDwords,
  1343. LONG lDelta, LONG lDeltaX8, PULONG pulBasePat, PULONG pulPatMax )
  1344. {
  1345. ULONG ulUniqueScans;
  1346. LONG lCurYTop;
  1347. ULONG *pulPatPtr;
  1348. LONG lMiddleBytes;
  1349. ULONG ulPattern;
  1350. ULONG ulNumScans;
  1351. ULONG *pulTrg;
  1352. ULONG ulRightDestMaskedPattern;
  1353. ULONG ulLeftDestMaskedPattern;
  1354. lMiddleBytes = lMiddleDwords << 2;
  1355. lCurYTop = prcl->top;
  1356. pulPatPtr = pulBasePat + ((lCurYTop - ppbf->yPat) & 0x07);
  1357. // Loop through up to all 8 pattern bytes, rotating into dword alignment,
  1358. // generating the left and right masked versions, and drawing all lines
  1359. // that use each pattern byte before proceeding to the next pattern byte
  1360. // Do either all 8 pattern scans or the number of scans the fill is high,
  1361. // whichever is less
  1362. ulUniqueScans = 8;
  1363. if ((prcl->bottom - prcl->top) < 8)
  1364. {
  1365. ulUniqueScans = prcl->bottom - prcl->top;
  1366. }
  1367. while (ulUniqueScans--)
  1368. {
  1369. // Point to scan to fill, then advance to next scan for next time
  1370. pulTrg = pulTrgBase;
  1371. pulTrgBase = (ULONG *)(((UCHAR *)pulTrgBase) + lDelta);
  1372. // Set up the number of scans to fill with this pattern scan, given
  1373. // that we'll do every eighth scan
  1374. ulNumScans = (prcl->bottom - lCurYTop + 7) >> 3;
  1375. lCurYTop++; // we'll start on the next destination scan for the
  1376. // next pattern scan
  1377. // Set up the appropriately rotated version of the current pattern scan
  1378. ulPattern = *pulPatPtr;
  1379. // Advance the pattern pointer to the next pattern scan
  1380. if (++pulPatPtr == pulPatMax)
  1381. {
  1382. pulPatPtr = pulBasePat;
  1383. }
  1384. // Draw all Y scans for this pattern byte
  1385. switch(ulFillType)
  1386. {
  1387. case LEFT_MIDDLE_RIGHT:
  1388. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1389. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  1390. do
  1391. {
  1392. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1393. ulLeftDestMaskedPattern;
  1394. RtlFillMemoryUlong (pulTrg+1, lMiddleBytes, ulPattern);
  1395. *(pulTrg+lMiddleDwords+1) =
  1396. (*(pulTrg+lMiddleDwords+1) & ulRightDestMask) |
  1397. ulRightDestMaskedPattern;
  1398. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1399. } while (--ulNumScans);
  1400. break;
  1401. case LEFT_MIDDLE:
  1402. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1403. do
  1404. {
  1405. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1406. ulLeftDestMaskedPattern;
  1407. RtlFillMemoryUlong (pulTrg+1, lMiddleBytes, ulPattern);
  1408. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1409. } while (--ulNumScans);
  1410. break;
  1411. case MIDDLE_RIGHT:
  1412. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  1413. do
  1414. {
  1415. RtlFillMemoryUlong (pulTrg, lMiddleBytes, ulPattern);
  1416. *(pulTrg+lMiddleDwords) =
  1417. (*(pulTrg+lMiddleDwords) & ulRightDestMask) |
  1418. ulRightDestMaskedPattern;
  1419. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1420. } while (--ulNumScans);
  1421. break;
  1422. case MIDDLE:
  1423. do
  1424. {
  1425. RtlFillMemoryUlong (pulTrg, lMiddleBytes, ulPattern);
  1426. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1427. } while (--ulNumScans);
  1428. break;
  1429. case LEFT_MIDDLE_RIGHT_SHORT:
  1430. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1431. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  1432. do
  1433. {
  1434. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1435. ulLeftDestMaskedPattern;
  1436. switch(lMiddleDwords)
  1437. {
  1438. case 9:
  1439. *(pulTrg+9) = ulPattern;
  1440. case 8:
  1441. *(pulTrg+8) = ulPattern;
  1442. case 7:
  1443. *(pulTrg+7) = ulPattern;
  1444. case 6:
  1445. *(pulTrg+6) = ulPattern;
  1446. case 5:
  1447. *(pulTrg+5) = ulPattern;
  1448. case 4:
  1449. *(pulTrg+4) = ulPattern;
  1450. case 3:
  1451. *(pulTrg+3) = ulPattern;
  1452. case 2:
  1453. *(pulTrg+2) = ulPattern;
  1454. case 1:
  1455. *(pulTrg+1) = ulPattern;
  1456. break;
  1457. }
  1458. *(pulTrg+lMiddleDwords+1) =
  1459. (*(pulTrg+lMiddleDwords+1) & ulRightDestMask) |
  1460. ulRightDestMaskedPattern;
  1461. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1462. } while (--ulNumScans);
  1463. break;
  1464. case LEFT_MIDDLE_SHORT:
  1465. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1466. do
  1467. {
  1468. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1469. ulLeftDestMaskedPattern;
  1470. switch(lMiddleDwords)
  1471. {
  1472. case 9:
  1473. *(pulTrg+9) = ulPattern;
  1474. case 8:
  1475. *(pulTrg+8) = ulPattern;
  1476. case 7:
  1477. *(pulTrg+7) = ulPattern;
  1478. case 6:
  1479. *(pulTrg+6) = ulPattern;
  1480. case 5:
  1481. *(pulTrg+5) = ulPattern;
  1482. case 4:
  1483. *(pulTrg+4) = ulPattern;
  1484. case 3:
  1485. *(pulTrg+3) = ulPattern;
  1486. case 2:
  1487. *(pulTrg+2) = ulPattern;
  1488. case 1:
  1489. *(pulTrg+1) = ulPattern;
  1490. break;
  1491. }
  1492. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1493. } while (--ulNumScans);
  1494. break;
  1495. case MIDDLE_RIGHT_SHORT:
  1496. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  1497. do
  1498. {
  1499. switch(lMiddleDwords)
  1500. {
  1501. case 9:
  1502. *(pulTrg+8) = ulPattern;
  1503. case 8:
  1504. *(pulTrg+7) = ulPattern;
  1505. case 7:
  1506. *(pulTrg+6) = ulPattern;
  1507. case 6:
  1508. *(pulTrg+5) = ulPattern;
  1509. case 5:
  1510. *(pulTrg+4) = ulPattern;
  1511. case 4:
  1512. *(pulTrg+3) = ulPattern;
  1513. case 3:
  1514. *(pulTrg+2) = ulPattern;
  1515. case 2:
  1516. *(pulTrg+1) = ulPattern;
  1517. case 1:
  1518. *(pulTrg) = ulPattern;
  1519. break;
  1520. }
  1521. *(pulTrg+lMiddleDwords) =
  1522. (*(pulTrg+lMiddleDwords) & ulRightDestMask) |
  1523. ulRightDestMaskedPattern;
  1524. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1525. } while (--ulNumScans);
  1526. break;
  1527. case MIDDLE_SHORT:
  1528. do
  1529. {
  1530. switch(lMiddleDwords)
  1531. {
  1532. case 9:
  1533. *(pulTrg+8) = ulPattern;
  1534. case 8:
  1535. *(pulTrg+7) = ulPattern;
  1536. case 7:
  1537. *(pulTrg+6) = ulPattern;
  1538. case 6:
  1539. *(pulTrg+5) = ulPattern;
  1540. case 5:
  1541. *(pulTrg+4) = ulPattern;
  1542. case 4:
  1543. *(pulTrg+3) = ulPattern;
  1544. case 3:
  1545. *(pulTrg+2) = ulPattern;
  1546. case 2:
  1547. *(pulTrg+1) = ulPattern;
  1548. case 1:
  1549. *(pulTrg) = ulPattern;
  1550. break;
  1551. }
  1552. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1553. } while (--ulNumScans);
  1554. break;
  1555. case LEFT_RIGHT:
  1556. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1557. ulRightDestMaskedPattern = ulPattern & ulRightPatMask;
  1558. do
  1559. {
  1560. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1561. ulLeftDestMaskedPattern;
  1562. *(pulTrg+1) = (*(pulTrg+1) & ulRightDestMask) |
  1563. ulRightDestMaskedPattern;
  1564. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1565. } while (--ulNumScans);
  1566. break;
  1567. case LEFT:
  1568. ulLeftDestMaskedPattern = ulPattern & ulLeftPatMask;
  1569. do
  1570. {
  1571. *pulTrg = (*pulTrg & ulLeftDestMask) |
  1572. ulLeftDestMaskedPattern;
  1573. pulTrg = (ULONG *)(((UCHAR *)pulTrg) + lDeltaX8);
  1574. } while (--ulNumScans);
  1575. break;
  1576. }
  1577. }
  1578. }
  1579. /******************************Public*Routine******************************\
  1580. * vPatCpyRect1_8x8
  1581. *
  1582. * Tiles an 8x8 pattern to 1 bpp bitmaps, for SRCCOPY rasterop only.
  1583. * Fills however many rectangles are specified by crcl
  1584. * Assumes pattern bytes are contiguous (lDelta for pattern is 4).
  1585. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-7.
  1586. * Assumes there is at least one rectangle to fill.
  1587. *
  1588. * History:
  1589. * 17-Nov-1992 -by- Stephen Estrop [StephenE]
  1590. * Wrote it.
  1591. \**************************************************************************/
  1592. VOID vPatCpyRect1_8x8(PATBLTFRAME *ppbf, INT crcl)
  1593. {
  1594. PRECTL prcl;
  1595. ULONG *pulTrgBase;
  1596. int ulFillType;
  1597. ULONG ulRightPatMask;
  1598. ULONG ulLeftPatMask;
  1599. ULONG ulRightDestMask;
  1600. ULONG ulLeftDestMask;
  1601. LONG lMiddleDwords;
  1602. LONG lDelta;
  1603. LONG lDeltaX8;
  1604. ULONG aulRotatedPat[8];
  1605. UCHAR ucPatRotateRight;
  1606. UCHAR ucPatRotateLeft;
  1607. ULONG ulPattern;
  1608. ULONG *pulPatPtr;
  1609. ULONG *pulPatRot;
  1610. ULONG *pulPatMax;
  1611. extern ULONG aulMsk[]; // Defined in solid.cxx
  1612. //
  1613. // Point to list of rectangles to fill
  1614. //
  1615. prcl = (RECTL *)ppbf->pvObj;
  1616. //
  1617. // Offset to next scan, offset to every eighth scan
  1618. //
  1619. lDeltaX8 = (lDelta = ppbf->lDeltaTrg) << 3;
  1620. //
  1621. // Loop through all rectangles to fill
  1622. //
  1623. do {
  1624. //
  1625. // Set up AND/OR masks for partial-dword edges, for masking both the
  1626. // pattern dword and the destination dword (the pattern and destination
  1627. // masks are complementary). A solid dword is 0 for dest, -1 for
  1628. // pattern
  1629. //
  1630. ulLeftPatMask = aulMsk[prcl->left & 31];
  1631. ulLeftDestMask = ~ulLeftPatMask;
  1632. if ((ulRightDestMask = aulMsk[prcl->right & 31]) == 0xFFFFFFFF)
  1633. {
  1634. ulRightDestMask = 0x00; // force solid to -1 for pattern
  1635. }
  1636. ulRightPatMask = ~ulRightDestMask;
  1637. //
  1638. // Point to the first dword to fill
  1639. //
  1640. pulTrgBase = (ULONG *) (((BYTE *) ppbf->pvTrg) +
  1641. (ppbf->lDeltaTrg * prcl->top)) + (prcl->left >> 5);
  1642. //
  1643. // Number of whole middle dwords/bytes to fill a dword at a time
  1644. //
  1645. lMiddleDwords = (LONG)(prcl->right >> 5) -
  1646. ((LONG)(prcl->left + 31 ) >> 5);
  1647. //
  1648. // Set up for the appropriate fill, given partial dwords at edges and
  1649. // narrow cases
  1650. //
  1651. switch (lMiddleDwords + 1)
  1652. {
  1653. case 1: // left and right, but no middle, or
  1654. // possibly just one, partial, dword
  1655. if ((ulLeftDestMask != 0) && (ulRightDestMask != 0)) {
  1656. // Left and right, but no middle
  1657. ulFillType = LEFT_RIGHT;
  1658. break;
  1659. }
  1660. // Note fallthrough in case where one of the masks is 0, meaning we
  1661. // have a single, partial dword
  1662. case 0: // just one, partial, dword, which
  1663. // we'll treat as a left edge
  1664. ulFillType = LEFT;
  1665. ulLeftPatMask &= ulRightPatMask;
  1666. ulLeftDestMask = ~ulLeftPatMask;
  1667. break;
  1668. case 2: // special case narrow cases, to avoid RTL
  1669. case 3: // call overhead and REP STOSD startup overhead
  1670. case 4:
  1671. case 5:
  1672. case 6:
  1673. case 7:
  1674. case 8:
  1675. case 9:
  1676. case 10:
  1677. if (ulLeftDestMask == 0)
  1678. {
  1679. if (ulRightDestMask == 0)
  1680. {
  1681. ulFillType = MIDDLE_SHORT;
  1682. }
  1683. else
  1684. {
  1685. ulFillType = MIDDLE_RIGHT_SHORT;
  1686. }
  1687. }
  1688. else
  1689. {
  1690. if (ulRightDestMask == 0)
  1691. {
  1692. ulFillType = LEFT_MIDDLE_SHORT;
  1693. }
  1694. else
  1695. {
  1696. ulFillType = LEFT_MIDDLE_RIGHT_SHORT;
  1697. }
  1698. }
  1699. break;
  1700. default:
  1701. if (ulLeftDestMask == 0)
  1702. {
  1703. if (ulRightDestMask == 0)
  1704. {
  1705. ulFillType = MIDDLE;
  1706. }
  1707. else
  1708. {
  1709. ulFillType = MIDDLE_RIGHT;
  1710. }
  1711. }
  1712. else
  1713. {
  1714. if (ulRightDestMask == 0)
  1715. {
  1716. ulFillType = LEFT_MIDDLE;
  1717. }
  1718. else
  1719. {
  1720. ulFillType = LEFT_MIDDLE_RIGHT;
  1721. }
  1722. }
  1723. break;
  1724. }
  1725. //
  1726. // Set up the shifts to produce the rotation effect to align the
  1727. // pattern as specified (the results of the two shifts are ORed
  1728. // together to emulate the rotate, because C can't do rotations
  1729. // directly)
  1730. //
  1731. ucPatRotateRight = (UCHAR) ppbf->xPat;
  1732. ucPatRotateLeft = (sizeof(ULONG) * 8) - ucPatRotateRight;
  1733. //
  1734. // Construct a replicated and aligned pattern.
  1735. //
  1736. pulPatPtr = (ULONG *)ppbf->pvPat,
  1737. pulPatMax = (ULONG *)ppbf->pvPat + 8,
  1738. pulPatRot = aulRotatedPat;
  1739. while ( pulPatPtr < pulPatMax ) {
  1740. //
  1741. // Assume only the first 8 bits are good, so replicate these.
  1742. //
  1743. ulPattern = *pulPatPtr++ >> 24;
  1744. ulPattern |= ulPattern << 8;
  1745. ulPattern |= ulPattern << 16;
  1746. //
  1747. // Rotate the pattern to align it correctly
  1748. //
  1749. if (ucPatRotateRight) {
  1750. ulPattern = (ulPattern >> ucPatRotateRight) |
  1751. (ulPattern << ucPatRotateLeft);
  1752. }
  1753. *pulPatRot++ = ulPattern;
  1754. }
  1755. //
  1756. // Do the PatBlt to this rectangle
  1757. //
  1758. pulPatMax = aulRotatedPat + 8;
  1759. vPatternCopyLoop(prcl,pulTrgBase,ppbf,ulFillType,ulRightPatMask,
  1760. ulLeftPatMask,ulRightDestMask,ulLeftDestMask,lMiddleDwords,
  1761. lDelta,lDeltaX8,aulRotatedPat,pulPatMax);
  1762. //
  1763. // Point to the next rectangle to fill, if there is one
  1764. //
  1765. prcl++;
  1766. }
  1767. while (--crcl);
  1768. }
  1769. /******************************Public*Routine******************************\
  1770. * vPatCpyRect1_6x6
  1771. *
  1772. * Tiles an 6x6 pattern to 1 bpp bitmaps, for SRCCOPY rasterop only.
  1773. * Fills however many rectangles are specified by crcl
  1774. * Assumes pattern bytes are contiguous (lDelta for pattern is 8).
  1775. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-5.
  1776. * Assumes there is at least one rectangle to fill.
  1777. *
  1778. * History:
  1779. * 23-Nov-1992 -by- Stephen Estrop [StephenE]
  1780. * Wrote it.
  1781. *
  1782. \**************************************************************************/
  1783. VOID vPatCpyRect1_6x6(PATBLTFRAME *ppbf, INT crcl)
  1784. {
  1785. UCHAR ucPatRotateRight;
  1786. UCHAR ucPatRotateLeft;
  1787. PRECTL prcl;
  1788. /*
  1789. ** lDelta is offset to the next scan in bytes, lDelta6 is the offset to
  1790. ** the next repeated scan in bytes.
  1791. */
  1792. LONG lDelta;
  1793. LONG lDelta6;
  1794. /*
  1795. ** pulTrgBase points to the first DWORD of the target rectangle in the
  1796. ** bitmap.
  1797. */
  1798. ULONG *pulTrgBase;
  1799. ULONG *pulTrg;
  1800. ULONG *pulTrgStart; // ptr to first DWORD in scan
  1801. /*
  1802. ** The pattern repeats in the LCM of 32 and 6 bits, which is 96 bits or
  1803. ** 3 Dwords. We actually repeat the pattern into 4 Dwords, this makes it
  1804. ** easier to handle the LEFT_MIDLLE and LEFT_MIDDLE_RIGHT cases.
  1805. */
  1806. ULONG aulPatternRepeat[4];
  1807. ULONG ulLeftPatMask;
  1808. ULONG ulLeftDestMask;
  1809. ULONG ulLeftDestMaskedPattern;
  1810. ULONG ulRightPatMask;
  1811. ULONG ulRightDestMask;
  1812. ULONG ulRightDestMaskedPattern;
  1813. int ulFillType;
  1814. LONG lMiddleBytes;
  1815. LONG lMiddleDwords;
  1816. LONG lMidDwords_div3;
  1817. LONG lMidDwords_mod3;
  1818. LONG lStartingDword;
  1819. ULONG *pulPatSrc;
  1820. ULONG *pulPatPtr;
  1821. ULONG *pulPatMax;
  1822. ULONG ulPattern;
  1823. LONG lCurYTop;
  1824. ULONG ulUniqueScans;
  1825. ULONG ulNumScans;
  1826. ULONG ulTemp;
  1827. UCHAR *pucTemp = (UCHAR *)&ulTemp;
  1828. LONG count;
  1829. extern ULONG aulMsk[]; // Defined in solid.cxx
  1830. /*
  1831. ** Point to list of rectangles to fill
  1832. */
  1833. prcl = (RECTL *)ppbf->pvObj;
  1834. /*
  1835. ** Offset to next scan, offset to every sixth scan
  1836. */
  1837. lDelta = ppbf->lDeltaTrg;
  1838. lDelta6 = lDelta * 6;
  1839. /*
  1840. ** Loop through all rectangles to fill
  1841. */
  1842. do {
  1843. /*
  1844. ** Set up AND/OR masks for partial-dword edges, for masking both the
  1845. ** pattern dword and the destination dword (the pattern and destination
  1846. ** masks are complementary). A solid dword is 0 for dest, -1 for
  1847. ** pattern
  1848. */
  1849. ulLeftPatMask = aulMsk[prcl->left & 31];
  1850. ulLeftDestMask = ~ulLeftPatMask;
  1851. if ((ulRightDestMask = aulMsk[prcl->right & 31]) == 0xFFFFFFFF)
  1852. {
  1853. ulRightDestMask = 0x00; // force solid to -1 for pattern
  1854. }
  1855. ulRightPatMask = ~ulRightDestMask;
  1856. /*
  1857. ** Point to the first dword to fill
  1858. */
  1859. pulTrgBase = (ULONG *) (((BYTE *) ppbf->pvTrg) +
  1860. (ppbf->lDeltaTrg * prcl->top)) + (prcl->left >> 5);
  1861. /*
  1862. ** Number of whole middle dwords/bytes to fill a dword at a time
  1863. */
  1864. lMiddleDwords = (LONG)(prcl->right >> 5) -
  1865. ((LONG)(prcl->left + 31 ) >> 5);
  1866. switch ( lMiddleDwords + 1 ) {
  1867. case 1:
  1868. if ( (ulLeftDestMask != 0) && (ulRightDestMask != 0) ) {
  1869. /*
  1870. ** left and right but no middle, or possible just one partial
  1871. ** dword.
  1872. */
  1873. ulFillType = LEFT_RIGHT;
  1874. break;
  1875. }
  1876. /*
  1877. ** Note fall thru in case where one off the masks is 0, meaning that we
  1878. ** have a single partial dword which we will treat as a LEFT fill type.
  1879. */
  1880. case 0:
  1881. ulFillType = LEFT;
  1882. ulLeftPatMask &= ulRightPatMask;
  1883. ulLeftDestMask = ~ulLeftPatMask;
  1884. break;
  1885. /*
  1886. ** Won't bother with short cases yet!
  1887. */
  1888. default:
  1889. if ( ulLeftDestMask == 0 ) {
  1890. if ( ulRightDestMask == 0 ) {
  1891. ulFillType = MIDDLE;
  1892. }
  1893. else {
  1894. ulFillType = MIDDLE_RIGHT;
  1895. }
  1896. }
  1897. else {
  1898. if ( ulRightDestMask == 0 ) {
  1899. ulFillType = LEFT_MIDDLE;
  1900. }
  1901. else {
  1902. /* most likely case ?? */
  1903. ulFillType = LEFT_MIDDLE_RIGHT;
  1904. }
  1905. }
  1906. }
  1907. /*
  1908. ** Pre-calculate some inner loop constants
  1909. **
  1910. ** Set up the shifts to produce the rotation effect to align the
  1911. ** pattern as specified (the results of the two shifts are ORed
  1912. ** together to emulate the rotate, because C can't do rotations
  1913. ** directly)
  1914. */
  1915. lCurYTop = prcl->top;
  1916. /*
  1917. ** Look for the case when (lCurYTop - ppbf->yPat) is less than zero.
  1918. ** (Note: ppbf->yPat can only be in the range 0-5). If we don't do
  1919. ** this we could end up with a negative value being added to the
  1920. ** pattern pointer. What we really want here is a modulus operator
  1921. ** (C only has a remainder operator), we cannot use the & operator
  1922. ** to fake modulus because 6 is not a power of two.
  1923. ** When (lCurYTop - ppbf->yPat) == 0 the pattern is already correctly
  1924. ** aligned in the Y axis.
  1925. */
  1926. if ( count = lCurYTop - ppbf->yPat ) {
  1927. count %= 6;
  1928. count += 6;
  1929. count %= 6;
  1930. pulPatPtr = (ULONG *)ppbf->pvPat + (2 * count);
  1931. } else {
  1932. pulPatPtr = (ULONG *)ppbf->pvPat;
  1933. }
  1934. pulPatMax = (ULONG *)ppbf->pvPat + 12;
  1935. lMidDwords_div3 = lMiddleDwords / 3;
  1936. lMidDwords_mod3 = lMiddleDwords % 3;
  1937. lMiddleBytes = lMiddleDwords << 2;
  1938. lStartingDword = (prcl->left >> 5) % 3;
  1939. ucPatRotateRight = (UCHAR)ppbf->xPat;
  1940. ucPatRotateLeft = 6 - ucPatRotateRight;
  1941. ulUniqueScans = 6;
  1942. if ( (prcl->bottom - prcl->top) < 6 ) {
  1943. ulUniqueScans = prcl->bottom - prcl->top;
  1944. }
  1945. while ( ulUniqueScans-- ) {
  1946. /*
  1947. ** Point to the scan to fill then advance to the next scan for
  1948. ** next time thru the loop.
  1949. */
  1950. pulTrgStart = pulTrg = pulTrgBase;
  1951. pulTrgBase = (ULONG *)((PBYTE)pulTrgBase + lDelta);
  1952. /*
  1953. ** Set up the number of scans to fill with this pattern scan, given
  1954. ** that we'll do every 6th scan.
  1955. */
  1956. ulNumScans = (prcl->bottom - lCurYTop + 5) / 6;
  1957. lCurYTop++;
  1958. /*
  1959. ** Load the first 8 bits of the pattern in to *pucTemp and at the
  1960. ** same time right justify the 6 bit pattern.
  1961. */
  1962. *pucTemp = *(UCHAR *)pulPatPtr >> 2;
  1963. /*
  1964. ** Horizontaly align the 6 bit pattern.
  1965. */
  1966. if ( ucPatRotateRight ) {
  1967. ulPattern = (ULONG)((*pucTemp >> ucPatRotateRight) |
  1968. (*pucTemp << ucPatRotateLeft)) & 0x3F;
  1969. }
  1970. else {
  1971. ulPattern = (ULONG)*pucTemp;
  1972. }
  1973. pulPatSrc = aulPatternRepeat;
  1974. /*
  1975. ** Basically, we shift the pattern to correctly fill the 32 bit
  1976. ** DWORD. We then rearrange the bytes within the DWORD to account
  1977. ** for little endianess. I special case the LEFT fill type as it
  1978. ** only requires 1 DWORDs worth of pattern it seems a little over
  1979. ** the top to replicate 96 bits of pattern, this saving in
  1980. ** execution time is at the expense of slightly larger code size.
  1981. */
  1982. if ( ulFillType == LEFT ) {
  1983. /*
  1984. ** Select the correct left edge from the 3 pattern DWORDs.
  1985. */
  1986. if( lStartingDword == 0 ) {
  1987. *pulPatSrc = ((ulPattern << 26) | (ulPattern << 20) |
  1988. (ulPattern << 14) | (ulPattern << 8) |
  1989. (ulPattern << 2) | (ulPattern >> 4));
  1990. }
  1991. else if( lStartingDword == 1 ) {
  1992. *pulPatSrc = ((ulPattern << 28) | (ulPattern << 22) |
  1993. (ulPattern << 16) | (ulPattern << 10) |
  1994. (ulPattern << 4) | (ulPattern >> 2));
  1995. }
  1996. else { // lStartingDword must be 2
  1997. *pulPatSrc = ((ulPattern << 30) | (ulPattern << 24) |
  1998. (ulPattern << 18) | (ulPattern << 12) |
  1999. (ulPattern << 6) | (ulPattern ));
  2000. }
  2001. *pucTemp = *(((UCHAR *)pulPatSrc) + 3);
  2002. *(pucTemp+1) = *(((UCHAR *)pulPatSrc) + 2);
  2003. *(pucTemp+2) = *(((UCHAR *)pulPatSrc) + 1);
  2004. *(pucTemp+3) = *(((UCHAR *)pulPatSrc));
  2005. *pulPatSrc = *((ULONG *)pucTemp);
  2006. /*
  2007. ** Draw all the Y scans for this pattern
  2008. */
  2009. ulLeftDestMaskedPattern = *aulPatternRepeat & ulLeftPatMask;
  2010. do {
  2011. *pulTrg = (*pulTrg & ulLeftDestMask) | ulLeftDestMaskedPattern;
  2012. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2013. } while ( --ulNumScans );
  2014. }
  2015. /*
  2016. ** Otherwise, we replicate the 6 bit pattern into a 96 bit pattern.
  2017. ** We use the same pattern generating principle as that described
  2018. ** above.
  2019. */
  2020. else {
  2021. /*
  2022. ** Pattern bits 0 - 31
  2023. */
  2024. *pulPatSrc = ((ulPattern << 26) | (ulPattern << 20) |
  2025. (ulPattern << 14) | (ulPattern << 8) |
  2026. (ulPattern << 2) | (ulPattern >> 4));
  2027. *pucTemp = *(((UCHAR *)pulPatSrc) + 3);
  2028. *(pucTemp+1) = *(((UCHAR *)pulPatSrc) + 2);
  2029. *(pucTemp+2) = *(((UCHAR *)pulPatSrc) + 1);
  2030. *(pucTemp+3) = *(((UCHAR *)pulPatSrc));
  2031. *pulPatSrc++ = *((ULONG *)pucTemp);
  2032. /*
  2033. ** Pattern bits 32 - 63
  2034. */
  2035. *pulPatSrc = ((ulPattern << 28) | (ulPattern << 22) |
  2036. (ulPattern << 16) | (ulPattern << 10) |
  2037. (ulPattern << 4) | (ulPattern >> 2));
  2038. *pucTemp = *(((UCHAR *)pulPatSrc) + 3);
  2039. *(pucTemp+1) = *(((UCHAR *)pulPatSrc) + 2);
  2040. *(pucTemp+2) = *(((UCHAR *)pulPatSrc) + 1);
  2041. *(pucTemp+3) = *(((UCHAR *)pulPatSrc));
  2042. *pulPatSrc++ = *((ULONG *)pucTemp);
  2043. /*
  2044. ** Pattern bits 64 - 95
  2045. */
  2046. *pulPatSrc = ((ulPattern << 30) | (ulPattern << 24) |
  2047. (ulPattern << 18) | (ulPattern << 12) |
  2048. (ulPattern << 6) | (ulPattern ));
  2049. *pucTemp = *(((UCHAR *)pulPatSrc) + 3);
  2050. *(pucTemp+1) = *(((UCHAR *)pulPatSrc) + 2);
  2051. *(pucTemp+2) = *(((UCHAR *)pulPatSrc) + 1);
  2052. *(pucTemp+3) = *(((UCHAR *)pulPatSrc));
  2053. *pulPatSrc++ = *((ULONG *)pucTemp);
  2054. /*
  2055. ** Select the correct left edge from the 3 pattern DWORDs.
  2056. ** A case of 0 means that we already have the correct edge
  2057. ** of the pattern aligned.
  2058. */
  2059. if ( lStartingDword == 1 ) {
  2060. ulTemp = *aulPatternRepeat;
  2061. *aulPatternRepeat = *(aulPatternRepeat + 1);
  2062. *(aulPatternRepeat + 1) = *(aulPatternRepeat + 2);
  2063. *(aulPatternRepeat + 2) = ulTemp;
  2064. }
  2065. else if ( lStartingDword == 2 ) {
  2066. ulTemp = *(aulPatternRepeat + 2);
  2067. *(aulPatternRepeat + 2) = *(aulPatternRepeat + 1);
  2068. *(aulPatternRepeat + 1) = *aulPatternRepeat;
  2069. *aulPatternRepeat = ulTemp;
  2070. }
  2071. /*
  2072. ** Finally the 4th DWORD is just a copy of the first.
  2073. */
  2074. *pulPatSrc = *aulPatternRepeat;
  2075. }
  2076. /*
  2077. ** Draw all the Y scans for this pattern
  2078. */
  2079. switch ( ulFillType ) {
  2080. /*
  2081. ** We include this case to force the i386 compiler to use a
  2082. ** jump table.
  2083. */
  2084. case LEFT:
  2085. ulTemp = 0;
  2086. break;
  2087. case LEFT_RIGHT:
  2088. ulLeftDestMaskedPattern = *aulPatternRepeat & ulLeftPatMask;
  2089. ulRightDestMaskedPattern = *(aulPatternRepeat + 1) &
  2090. ulRightPatMask;
  2091. do {
  2092. *pulTrg = (*pulTrg & ulLeftDestMask) |
  2093. ulLeftDestMaskedPattern;
  2094. *(pulTrg + 1) = (*(pulTrg + 1) & ulRightDestMask) |
  2095. ulRightDestMaskedPattern;
  2096. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2097. } while ( --ulNumScans );
  2098. break;
  2099. case LEFT_MIDDLE_RIGHT:
  2100. ulLeftDestMaskedPattern = *aulPatternRepeat & ulLeftPatMask;
  2101. ulRightDestMaskedPattern =
  2102. *(aulPatternRepeat + 1 + lMidDwords_mod3) & ulRightPatMask;
  2103. /*
  2104. ** Do the first LEFT edge
  2105. */
  2106. *pulTrg = (*pulTrg & ulLeftDestMask) | ulLeftDestMaskedPattern;
  2107. /*
  2108. ** Now do first CENTER stripe
  2109. **
  2110. ** Copy the 96 bit pattern as many times as will fit in the
  2111. ** middle dword section.
  2112. */
  2113. for ( count = 0; count < lMidDwords_div3; count++ ) {
  2114. RtlCopyMemory( pulTrg + 1, aulPatternRepeat + 1, 12 );
  2115. pulTrg += 3;
  2116. }
  2117. /*
  2118. ** Do any Dwords that got truncated
  2119. */
  2120. if ( lMidDwords_mod3 ) {
  2121. RtlCopyMemory( pulTrg + 1, aulPatternRepeat + 1,
  2122. (UINT)(lMidDwords_mod3 << 2) );
  2123. pulTrg += lMidDwords_mod3;
  2124. }
  2125. /*
  2126. ** Now do the first RIGHT edge
  2127. */
  2128. *(pulTrg + 1) = (*(pulTrg + 1) & ulRightDestMask) |
  2129. ulRightDestMaskedPattern;
  2130. /*
  2131. ** Now copy the previously drawn scan line into all common scans
  2132. */
  2133. pulTrg = (ULONG *)((PBYTE)pulTrgStart + lDelta6);
  2134. while ( --ulNumScans ) {
  2135. *pulTrg = (*pulTrg & ulLeftDestMask) | ulLeftDestMaskedPattern;
  2136. RtlCopyMemory( pulTrg + 1, pulTrgStart + 1,
  2137. (UINT)lMiddleBytes );
  2138. *(pulTrg + 1 + lMiddleDwords) =
  2139. (*(pulTrg + 1 + lMiddleDwords) & ulRightDestMask) |
  2140. ulRightDestMaskedPattern;
  2141. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2142. }
  2143. break;
  2144. case LEFT_MIDDLE:
  2145. ulLeftDestMaskedPattern = *aulPatternRepeat & ulLeftPatMask;
  2146. /*
  2147. ** Do the first LEFT edge
  2148. */
  2149. *pulTrg = (*pulTrg & ulLeftDestMask) | ulLeftDestMaskedPattern;
  2150. /*
  2151. ** Now do first CENTER stripe
  2152. **
  2153. ** Copy the 96 bit pattern as many times as will fit in the
  2154. ** middle dword section.
  2155. */
  2156. for ( count = 0; count < lMidDwords_div3; count++ ) {
  2157. RtlCopyMemory( pulTrg + 1, aulPatternRepeat + 1, 12 );
  2158. pulTrg += 3;
  2159. }
  2160. /*
  2161. ** Do any Dwords that got truncated
  2162. */
  2163. if ( lMidDwords_mod3 ) {
  2164. RtlCopyMemory( pulTrg + 1, aulPatternRepeat + 1,
  2165. (UINT)(lMidDwords_mod3 << 2) );
  2166. }
  2167. /*
  2168. ** Now copy the previously drawn scan line into all common scans
  2169. */
  2170. pulTrg = (ULONG *)((PBYTE)pulTrgStart + lDelta6);
  2171. while ( --ulNumScans ) {
  2172. *pulTrg = (*pulTrg & ulLeftDestMask) |
  2173. ulLeftDestMaskedPattern;
  2174. RtlCopyMemory( pulTrg + 1, pulTrgStart + 1,
  2175. (UINT)lMiddleBytes );
  2176. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2177. }
  2178. break;
  2179. case MIDDLE:
  2180. /*
  2181. ** Copy the 96 bit pattern as many times as will fit in the
  2182. ** middle dword section.
  2183. */
  2184. for ( count = 0; count < lMidDwords_div3; count++ ) {
  2185. RtlCopyMemory( pulTrg, aulPatternRepeat, 12 );
  2186. pulTrg += 3;
  2187. }
  2188. /*
  2189. ** Do any Dwords that got truncated
  2190. */
  2191. if ( lMidDwords_mod3 ) {
  2192. RtlCopyMemory( pulTrg, aulPatternRepeat,
  2193. (UINT)(lMidDwords_mod3 << 2) );
  2194. }
  2195. /*
  2196. ** Now copy the previously drawn scan line into all common scans
  2197. */
  2198. pulTrg = (ULONG *)((PBYTE)pulTrgStart + lDelta6);
  2199. while ( --ulNumScans ) {
  2200. RtlCopyMemory( pulTrg, pulTrgStart, (UINT)lMiddleBytes );
  2201. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2202. }
  2203. break;
  2204. case MIDDLE_RIGHT:
  2205. ulRightDestMaskedPattern =
  2206. *(aulPatternRepeat + lMidDwords_mod3) & ulRightPatMask;
  2207. /*
  2208. ** Copy the 96 bit pattern as many times as will fit in the
  2209. ** middle dword section.
  2210. */
  2211. for ( count = 0; count < lMidDwords_div3; count++ ) {
  2212. RtlCopyMemory( pulTrg, aulPatternRepeat, 12 );
  2213. pulTrg += 3;
  2214. }
  2215. /*
  2216. ** Do any Dwords that got truncated
  2217. */
  2218. if ( lMidDwords_mod3 ) {
  2219. RtlCopyMemory( pulTrg, aulPatternRepeat,
  2220. (UINT)(lMidDwords_mod3 << 2) );
  2221. pulTrg += lMidDwords_mod3;
  2222. }
  2223. /*
  2224. ** Now do the first RIGHT edge
  2225. */
  2226. *pulTrg = (*pulTrg & ulRightDestMask) |
  2227. ulRightDestMaskedPattern;
  2228. /*
  2229. ** Now copy the previously drawn scan line into all
  2230. ** common scans
  2231. */
  2232. pulTrg = (ULONG *)((PBYTE)pulTrgStart + lDelta6);
  2233. while ( --ulNumScans ) {
  2234. RtlCopyMemory( pulTrg, pulTrgStart, (UINT)lMiddleBytes );
  2235. *(pulTrg + lMiddleDwords) =
  2236. (*(pulTrg + lMiddleDwords) & ulRightDestMask) |
  2237. ulRightDestMaskedPattern;
  2238. pulTrg = (ULONG *)((PBYTE)pulTrg + lDelta6);
  2239. }
  2240. break;
  2241. }
  2242. /*
  2243. ** Advance the pattern pointer for the next pattern scan
  2244. */
  2245. pulPatPtr += 2;
  2246. if ( pulPatPtr == pulPatMax ) {
  2247. pulPatPtr = (ULONG *)ppbf->pvPat;
  2248. }
  2249. }
  2250. /*
  2251. ** Point to the next rectangle to fill, if there is one
  2252. */
  2253. prcl++;
  2254. }
  2255. while (--crcl);
  2256. }
  2257. /******************************Public*Routine******************************\
  2258. *
  2259. * Routine Name:
  2260. *
  2261. * vPatCpyRect8_8x8
  2262. *
  2263. * Routine Description:
  2264. *
  2265. * Tiles an 8x8 pattern to 8 bpp bitmaps, for SRCCOPY rasterop only.
  2266. * Fills however many rectangles are specified by crcl
  2267. * Assumes pattern bytes are contiguous.
  2268. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-7.
  2269. * Assumes there is at least one rectangle to fill.
  2270. *
  2271. * NOTE: We will sometimes be passed empty rectangles!
  2272. *
  2273. * Arguments
  2274. *
  2275. * ppbf - pointer to PATBLTFRAME pattern information
  2276. * crcl - Rectangle count
  2277. *
  2278. * Returns
  2279. *
  2280. * VOID, this functions may not fail
  2281. *
  2282. * History:
  2283. * 18-Oct-1993 -by- Mark Enstrom [marke] - simplified for 8bpp
  2284. * 17-Nov-1992 -by- Reza Baghai [rezab]
  2285. * Adapted from vPatCpyRect4_8x8.
  2286. *
  2287. \**************************************************************************/
  2288. VOID vPatCpyRect8_8x8(PATBLTFRAME *ppbf, INT crcl)
  2289. {
  2290. PULONG pulTrg;
  2291. PULONG pulTrgTmp;
  2292. LONG lDeltaTrg8;
  2293. ULONG PatRotate;
  2294. ULONG PatRotateRight;
  2295. ULONG PatRotateLeft;
  2296. PRECTL prcl;
  2297. LONG lDeltaPat;
  2298. ULONG cyPatternTop;
  2299. ULONG cyVenetianTop;
  2300. ULONG cyVenetian;
  2301. ULONG ulPatternEven;
  2302. ULONG ulPatternOdd;
  2303. ULONG ulffPattern[2];
  2304. ULONG ulTmp;
  2305. ULONG *pulPat;
  2306. ULONG *pulPatMax;
  2307. ULONG *pulPatBase;
  2308. ULONG PatOffsetY;
  2309. FETCHFRAME ff;
  2310. #if DBG_PAT_CPY
  2311. if (DbgPatCpy >= 1) {
  2312. DbgPrint("vPatCpyRect8_8x8 @ppbf = 0x%p crcl = %li\n",ppbf,crcl);
  2313. DbgPrint("pvTrg = 0x%p, pvPat = 0x%p\n",ppbf->pvTrg,ppbf->pvPat);
  2314. DbgPrint("xPat = %li, yPat = %li\n",ppbf->xPat,ppbf->yPat);
  2315. }
  2316. #endif
  2317. //
  2318. // Point to list of rectangles to fill
  2319. //
  2320. prcl = (RECTL *) ppbf->pvObj;
  2321. //
  2322. // set up pattern access vars and rotation
  2323. //
  2324. pulPatBase = (ULONG *)ppbf->pvPat;
  2325. PatRotate = (ppbf->xPat & 7);
  2326. PatRotateLeft = (ppbf->xPat & 3);
  2327. PatRotateRight = 4 - PatRotateLeft;
  2328. //
  2329. // mupliply by 8 to get byte shift values
  2330. //
  2331. PatRotateRight <<= 3;
  2332. PatRotateLeft <<= 3;
  2333. //
  2334. // Remember where the pattern ends, for wrapping
  2335. //
  2336. lDeltaPat = 12;
  2337. pulPatMax = (ULONG *)(((BYTE *)pulPatBase) + (lDeltaPat << 3));
  2338. #if DBG_PAT_CPY
  2339. if (DbgPatCpy >= 2) {
  2340. DbgPrint(" Pattern Base = 0x%p\n",pulPatBase);
  2341. DbgPrint(" Pattern Max = 0x%p\n",pulPatMax);
  2342. DbgPrint(" Pattern Delta = 0x%lx\n",lDeltaPat);
  2343. DbgPrint(" Pattern Rotate = 0x%lx\n",PatRotate);
  2344. }
  2345. #endif
  2346. //
  2347. // Loop through all rectangles to fill
  2348. //
  2349. do {
  2350. //
  2351. // are these gaurenteed to be well ordered rectangles?
  2352. //
  2353. //
  2354. // set up begin and end cases as well as middle case for
  2355. // each rect as well as wether to start on even or odd
  2356. //
  2357. #if DBG_PAT_CPY
  2358. if (DbgPatCpy >= 1)
  2359. {
  2360. DbgPrint(" Fill Rect %li,%li to %li,%li\n",
  2361. prcl->left,
  2362. prcl->top,
  2363. prcl->right,
  2364. prcl->bottom
  2365. );
  2366. }
  2367. #endif
  2368. LONG cy = prcl->bottom - prcl->top;
  2369. LONG cx = prcl->right - prcl->left;
  2370. //
  2371. // determine start and end cases for the entire rect
  2372. //
  2373. //
  2374. // Simple start cases: End cases:
  2375. //
  2376. // �����Ŀ �Ŀ
  2377. // �1�2�3� 1 �0� 1
  2378. // ������� ���
  2379. // ���Ŀ ���Ŀ
  2380. // �2�3� 2 �0�1� 2
  2381. // ����� �����
  2382. // �Ŀ �����Ŀ
  2383. // �3� 3 �0�1�2� 3
  2384. // ��� �������
  2385. //
  2386. // Start/end combination
  2387. //
  2388. // �Ŀ
  2389. // �1� 1 + 3
  2390. // ���
  2391. // ���Ŀ
  2392. // �1�2� 1 + 4
  2393. // �����
  2394. // �Ŀ
  2395. // �2� 2 + 4
  2396. // ���
  2397. //
  2398. //
  2399. LONG StartCase = prcl->left & 0x03;
  2400. LONG EndCase = prcl->right & 0x03;
  2401. LONG cxDword = cx - EndCase - ((4-StartCase) & 0x03);
  2402. if (cxDword < 0) {
  2403. cxDword = 0;
  2404. } else {
  2405. cxDword >>= 2;
  2406. }
  2407. if (StartCase == 1)
  2408. {
  2409. if (cx == 1)
  2410. {
  2411. StartCase = 4;
  2412. EndCase = 0;
  2413. } else if (cx == 2) {
  2414. StartCase = 5;
  2415. EndCase = 0;
  2416. }
  2417. } else if (StartCase == 2)
  2418. {
  2419. if (cx == 1) {
  2420. StartCase = 6;
  2421. EndCase = 0;
  2422. }
  2423. }
  2424. //
  2425. // calc the index for loading even and odd pattern DWORDS
  2426. //
  2427. LONG StartOffset = (prcl->left & 0x04) >> 2;
  2428. LONG StartOffsetNot = (~StartOffset) & 0x01;
  2429. //
  2430. // calculate the DWORD address of pat scan line and
  2431. // of the destination
  2432. //
  2433. PatOffsetY = (ULONG)((prcl->top - ppbf->yPat) & 0x07);
  2434. pulPat = (PULONG)((PBYTE)pulPatBase + lDeltaPat * PatOffsetY);
  2435. pulTrgTmp = (PULONG)(((PBYTE)ppbf->pvTrg +
  2436. ppbf->lDeltaTrg * prcl->top +
  2437. (prcl->left & ~0x03)));
  2438. //
  2439. // The first 'cyPatternTop' scans of the pattern will each be tiled
  2440. // 'cyVenetianTop' times into the destination rectangle. Then, the
  2441. // next '8 - cyPatternTop' scans of the pattern will each be tiled
  2442. // 'cyVenetianTop - 1' times into the destination rectangle.
  2443. //
  2444. cyPatternTop = (cy & 7);
  2445. cyVenetianTop = (cy >> 3) + 1;
  2446. //
  2447. // lDeltaTrg8 is the offset for 8 Trg scan lines
  2448. //
  2449. lDeltaTrg8 = ppbf->lDeltaTrg << 3;
  2450. #if DBG_PAT_CPY
  2451. if (DbgPatCpy >= 2)
  2452. {
  2453. DbgPrint(" Start Case = %li, EndCase = %li cxDword = %li\n",StartCase,EndCase,cxDword);
  2454. DbgPrint(" StartOffset = %li\n",StartOffset);
  2455. DbgPrint(" pulPat = 0x%p\n",pulPat);
  2456. DbgPrint(" Pat Y = %li\n",PatOffsetY);
  2457. DbgPrint(" pulTrg = 0x%p\n",pulTrgTmp);
  2458. }
  2459. #endif
  2460. //
  2461. // for each scan line
  2462. //
  2463. ff.pvPat = (PVOID)&ulffPattern;
  2464. ff.xPat = 0;
  2465. ff.cxPat = 8;
  2466. ff.culWidth = 2;
  2467. //
  2468. // fill every eigth scan line at the same time.
  2469. //
  2470. if (cy > 8) {
  2471. cy = 8;
  2472. }
  2473. while (cy--) {
  2474. PULONG pulScanTrg;
  2475. ULONG ulTmpPatEven;
  2476. ULONG ulTmpPatOdd;
  2477. //
  2478. // load up even and odd pat, rotate into dst alignment
  2479. //
  2480. if (ppbf->xPat == 0) {
  2481. //
  2482. // pattern is aligned
  2483. //
  2484. ulPatternEven = *(pulPat + StartOffset);
  2485. ulPatternOdd = *(pulPat + StartOffsetNot);
  2486. } else {
  2487. //
  2488. // pattern must be rotated
  2489. //
  2490. ulTmpPatEven = *(pulPat);
  2491. ulTmpPatOdd = *(pulPat + 1);
  2492. #if DBG_PAT_CPY
  2493. if (DbgPatCpy >= 2)
  2494. {
  2495. DbgPrint(" TmpPatEven = 0x%lx\n",ulTmpPatEven);
  2496. DbgPrint(" TmpPatOdd = 0x%lx\n",ulTmpPatOdd);
  2497. }
  2498. #endif
  2499. if (PatRotate < 4) {
  2500. ulPatternEven = (ulTmpPatEven << PatRotateLeft) |
  2501. (ulTmpPatOdd >> PatRotateRight);
  2502. ulPatternOdd = (ulTmpPatOdd << PatRotateLeft) |
  2503. (ulTmpPatEven >> PatRotateRight);
  2504. } else if (PatRotate == 4) {
  2505. ulPatternEven = ulTmpPatOdd;
  2506. ulPatternOdd = ulTmpPatEven;
  2507. } else {
  2508. ulPatternEven = (ulTmpPatEven >> PatRotateRight) |
  2509. (ulTmpPatOdd << PatRotateLeft);
  2510. ulPatternOdd = (ulTmpPatOdd >> PatRotateRight) |
  2511. (ulTmpPatEven << PatRotateLeft);
  2512. }
  2513. if (StartOffset != 0) {
  2514. //
  2515. // swap even and odd
  2516. //
  2517. ulTmpPatEven = ulPatternEven;
  2518. ulPatternEven = ulPatternOdd;
  2519. ulPatternOdd = ulTmpPatEven;
  2520. }
  2521. }
  2522. #if DBG_PAT_CPY
  2523. if (DbgPatCpy >= 2)
  2524. {
  2525. DbgPrint(" PatEven = 0x%lx\n",ulPatternEven);
  2526. DbgPrint(" PatOdd = 0x%lx\n",ulPatternOdd);
  2527. }
  2528. #endif
  2529. pulScanTrg = pulTrgTmp;
  2530. //
  2531. // do every eighth scan line
  2532. //
  2533. if (cyPatternTop-- == 0)
  2534. cyVenetianTop--;
  2535. cyVenetian = cyVenetianTop;
  2536. while (cyVenetian-- != 0) {
  2537. ULONG cxTmp = cxDword;
  2538. //
  2539. // pulTrg = beginning of next scan line
  2540. //
  2541. //
  2542. // assign temp patterns
  2543. //
  2544. ulTmpPatEven = ulPatternEven;
  2545. ulTmpPatOdd = ulPatternOdd;
  2546. pulTrg = pulScanTrg;
  2547. if (StartCase != 0)
  2548. {
  2549. switch (StartCase)
  2550. {
  2551. case 1:
  2552. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2553. *((PUSHORT)pulTrg+1) = (SHORT)(ulTmpPatEven >> 16);
  2554. break;
  2555. case 2:
  2556. *((PUSHORT)pulTrg+1) = (SHORT)(ulTmpPatEven >> 16);
  2557. break;
  2558. case 3:
  2559. *((PBYTE)pulTrg+3) = (BYTE)(ulTmpPatEven >> 24);
  2560. break;
  2561. case 4:
  2562. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2563. break;
  2564. case 5:
  2565. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2566. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2567. break;
  2568. case 6:
  2569. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2570. break;
  2571. }
  2572. pulTrg++;
  2573. //
  2574. // swap patterns
  2575. //
  2576. ulTmp = ulTmpPatEven;
  2577. ulTmpPatEven = ulTmpPatOdd;
  2578. ulTmpPatOdd = ulTmp;
  2579. }
  2580. if (cxDword > 7) {
  2581. ulffPattern[0] = ulTmpPatEven;
  2582. ulffPattern[1] = ulTmpPatOdd;
  2583. ff.culFill = cxDword;
  2584. ff.pvTrg = (PVOID)pulTrg;
  2585. vFetchAndCopy(&ff);
  2586. pulTrg += cxDword;
  2587. } else {
  2588. //
  2589. // dword pairs
  2590. //
  2591. while (cxTmp >= 2) {
  2592. *pulTrg = ulTmpPatEven;
  2593. *(pulTrg+1) = ulTmpPatOdd;
  2594. pulTrg += 2;
  2595. cxTmp -= 2;
  2596. }
  2597. //
  2598. // possible last dword
  2599. //
  2600. if (cxTmp) {
  2601. *pulTrg = ulTmpPatEven;
  2602. pulTrg++;
  2603. }
  2604. }
  2605. //
  2606. // end case if needed
  2607. //
  2608. if (EndCase != 0) {
  2609. //
  2610. // if cxDword is odd then the patterns must be swapped
  2611. //
  2612. if (cxDword & 0x01) {
  2613. ulTmpPatEven = ulTmpPatOdd;
  2614. }
  2615. switch (EndCase) {
  2616. case 1:
  2617. *(PBYTE)pulTrg = (BYTE)ulTmpPatEven;
  2618. break;
  2619. case 2:
  2620. *(PUSHORT)pulTrg = (USHORT)ulTmpPatEven;
  2621. break;
  2622. case 3:
  2623. *(PUSHORT)pulTrg = (USHORT)ulTmpPatEven;
  2624. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2625. break;
  2626. }
  2627. }
  2628. pulScanTrg = (PULONG)((PBYTE)pulScanTrg + lDeltaTrg8);
  2629. }
  2630. //
  2631. // inc dst and pat pointers
  2632. //
  2633. pulPat = (PULONG)((PBYTE)pulPat + lDeltaPat);
  2634. if (pulPat >= pulPatMax) {
  2635. pulPat = pulPatBase;
  2636. }
  2637. pulTrgTmp = (PULONG)((PBYTE)pulTrgTmp + ppbf->lDeltaTrg);
  2638. }
  2639. prcl++;
  2640. } while (--crcl);
  2641. }
  2642. /******************************Public*Routine******************************\
  2643. *
  2644. * Routine Name:
  2645. *
  2646. * vPatCpyRow8_8x8
  2647. *
  2648. * Routine Description:
  2649. *
  2650. * Tiles an 8x8 pattern to 8 bpp bitmaps, for SRCCOPY rasterop only.
  2651. * Fills however many rectangles are specified by crcl
  2652. * Assumes pattern bytes are contiguous.
  2653. * Assumes pattern X and Y origin (xPat and yPat) are in the range 0-7.
  2654. * Assumes there is at least one rectangle to fill.
  2655. *
  2656. * Arguments
  2657. *
  2658. * ppbf - pointer to PATBLTFRAME pattern information
  2659. * yStart - starting row, all following rows are consecutive
  2660. * crow - number of rows
  2661. *
  2662. * Returns
  2663. *
  2664. * VOID, this functions may not fail
  2665. *
  2666. * History:
  2667. * 08-Dec-1993 -by- Mark Enstrom [marke]
  2668. *
  2669. \**************************************************************************/
  2670. VOID vPatCpyRow8_8x8(PATBLTFRAME *ppbf, LONG yStart, INT crow)
  2671. {
  2672. PULONG pulTrg;
  2673. PULONG pulTrgTmp;
  2674. PUCHAR pjTrgScan;
  2675. LONG lDeltaTrg8;
  2676. ULONG PatRotate;
  2677. ULONG PatRotateRight;
  2678. ULONG PatRotateLeft;
  2679. PROW prow;
  2680. LONG lDeltaPat;
  2681. ULONG ulPatternEven;
  2682. ULONG ulPatternOdd;
  2683. ULONG ulffPattern[2];
  2684. ULONG ulTmp;
  2685. ULONG *pulPat;
  2686. ULONG *pulPatMax;
  2687. ULONG *pulPatBase;
  2688. ULONG PatOffsetY;
  2689. FETCHFRAME ff;
  2690. #if DBG_PAT_CPY
  2691. if (DbgPatCpy >= 1) {
  2692. DbgPrint("vPatCpyRect8_8x8 @ppbf = 0x%p crow = %li\n",ppbf,crow);
  2693. DbgPrint("pvTrg = 0x%p, pvPat = 0x%p\n",ppbf->pvTrg,ppbf->pvPat);
  2694. DbgPrint("xPat = %li, yPat = %li\n",ppbf->xPat,ppbf->yPat);
  2695. }
  2696. #endif
  2697. //
  2698. // Point to list of rows to fill
  2699. //
  2700. prow = (PROW) ppbf->pvObj;
  2701. //
  2702. // start row dst address
  2703. //
  2704. pjTrgScan = (PUCHAR)ppbf->pvTrg + ppbf->lDeltaTrg * yStart;
  2705. //
  2706. // start pattern offset
  2707. //
  2708. PatOffsetY = (ULONG)((yStart - ppbf->yPat) & 0x07);
  2709. //
  2710. // set up pattern access vars and rotation
  2711. //
  2712. pulPatBase = (ULONG *)ppbf->pvPat;
  2713. PatRotate = (ppbf->xPat & 7);
  2714. PatRotateLeft = (ppbf->xPat & 3);
  2715. PatRotateRight = 4 - PatRotateLeft;
  2716. //
  2717. // mupliply by 8 to get byte shift values
  2718. //
  2719. PatRotateRight <<= 3;
  2720. PatRotateLeft <<= 3;
  2721. //
  2722. // lDelta for 8bpp 8x8 patterns is hard coded to 12
  2723. //
  2724. lDeltaPat = 12;
  2725. //
  2726. // Remember where the pattern starts and where the pattern ends for wrapping
  2727. //
  2728. pulPat = (PULONG)((PBYTE)pulPatBase + lDeltaPat * PatOffsetY);
  2729. pulPatMax = (PULONG)(((PBYTE)pulPatBase) + (lDeltaPat << 3));
  2730. #if DBG_PAT_CPY
  2731. if (DbgPatCpy >= 2) {
  2732. DbgPrint(" Pattern Base = 0x%p\n",pulPatBase);
  2733. DbgPrint(" Pattern Max = 0x%p\n",pulPatMax);
  2734. DbgPrint(" Pattern Delta = 0x%lx\n",lDeltaPat);
  2735. DbgPrint(" Pattern Rotate = 0x%lx\n",PatRotate);
  2736. }
  2737. #endif
  2738. //
  2739. // Loop through all rows to fill
  2740. //
  2741. do {
  2742. //
  2743. // set up begin and end cases as well as middle case for
  2744. // each row as well as wether to start on even or odd
  2745. //
  2746. #if DBG_PAT_CPY
  2747. if (DbgPatCpy >= 1)
  2748. {
  2749. DbgPrint(" Fill Row %li to %li\n",
  2750. prow->left,
  2751. prow->right
  2752. );
  2753. }
  2754. #endif
  2755. LONG cx = prow->right - prow->left;
  2756. //
  2757. // determine start and end cases for the row
  2758. //
  2759. //
  2760. // Simple start cases: End cases:
  2761. //
  2762. // �����Ŀ �Ŀ
  2763. // �1�2�3� 1 �0� 1
  2764. // ������� ���
  2765. // ���Ŀ ���Ŀ
  2766. // �2�3� 2 �0�1� 2
  2767. // ����� �����
  2768. // �Ŀ �����Ŀ
  2769. // �3� 3 �0�1�2� 3
  2770. // ��� �������
  2771. //
  2772. // Start/end combination
  2773. //
  2774. // �Ŀ
  2775. // �1� 1 + 3
  2776. // ���
  2777. // ���Ŀ
  2778. // �1�2� 1 + 4
  2779. // �����
  2780. // �Ŀ
  2781. // �2� 2 + 4
  2782. // ���
  2783. //
  2784. //
  2785. LONG StartCase = prow->left & 0x03;
  2786. LONG EndCase = prow->right & 0x03;
  2787. LONG cxDword = cx - EndCase - ((4-StartCase) & 0x03);
  2788. if (cxDword < 0) {
  2789. cxDword = 0;
  2790. } else {
  2791. cxDword >>= 2;
  2792. }
  2793. if (StartCase == 1)
  2794. {
  2795. if (cx == 1)
  2796. {
  2797. StartCase = 4;
  2798. EndCase = 0;
  2799. } else if (cx == 2) {
  2800. StartCase = 5;
  2801. EndCase = 0;
  2802. }
  2803. } else if (StartCase == 2)
  2804. {
  2805. if (cx == 1) {
  2806. StartCase = 6;
  2807. EndCase = 0;
  2808. }
  2809. }
  2810. //
  2811. // calc the index for loading even and odd pattern DWORDS
  2812. //
  2813. LONG StartOffset = (prow->left & 0x04) >> 2;
  2814. LONG StartOffsetNot = (~StartOffset) & 0x01;
  2815. //
  2816. // calculate the DWORD address of pat scan line and
  2817. // of the destination
  2818. //
  2819. pulTrgTmp = (PULONG)(pjTrgScan + (prow->left & ~0x03));
  2820. //
  2821. // lDeltaTrg8 is the offset for 8 Trg scan lines
  2822. //
  2823. lDeltaTrg8 = ppbf->lDeltaTrg << 3;
  2824. #if DBG_PAT_CPY
  2825. if (DbgPatCpy >= 2)
  2826. {
  2827. DbgPrint(" Start Case = %li, EndCase = %li cxDword = %li\n",StartCase,EndCase,cxDword);
  2828. DbgPrint(" StartOffset = %li\n",StartOffset);
  2829. DbgPrint(" pulPat = 0x%p\n",pulPat);
  2830. DbgPrint(" Pat Y = %li\n",PatOffsetY);
  2831. DbgPrint(" pulTrg = 0x%p\n",pulTrgTmp);
  2832. }
  2833. #endif
  2834. //
  2835. // for each scan line
  2836. //
  2837. ff.pvPat = (PVOID)&ulffPattern;
  2838. ff.xPat = 0;
  2839. ff.cxPat = 8;
  2840. ff.culWidth = 2;
  2841. PULONG pulScanTrg;
  2842. ULONG ulTmpPatEven;
  2843. ULONG ulTmpPatOdd;
  2844. //
  2845. // load up even and odd pat, rotate into dst alignment
  2846. //
  2847. if (ppbf->xPat == 0) {
  2848. //
  2849. // pattern is aligned
  2850. //
  2851. ulPatternEven = *(pulPat + StartOffset);
  2852. ulPatternOdd = *(pulPat + StartOffsetNot);
  2853. } else {
  2854. //
  2855. // pattern must be rotated
  2856. //
  2857. ulTmpPatEven = *(pulPat);
  2858. ulTmpPatOdd = *(pulPat + 1);
  2859. #if DBG_PAT_CPY
  2860. if (DbgPatCpy >= 2)
  2861. {
  2862. DbgPrint(" TmpPatEven = 0x%lx\n",ulTmpPatEven);
  2863. DbgPrint(" TmpPatOdd = 0x%lx\n",ulTmpPatOdd);
  2864. }
  2865. #endif
  2866. if (PatRotate < 4) {
  2867. ulPatternEven = (ulTmpPatEven << PatRotateLeft) |
  2868. (ulTmpPatOdd >> PatRotateRight);
  2869. ulPatternOdd = (ulTmpPatOdd << PatRotateLeft) |
  2870. (ulTmpPatEven >> PatRotateRight);
  2871. } else if (PatRotate == 4) {
  2872. ulPatternEven = ulTmpPatOdd;
  2873. ulPatternOdd = ulTmpPatEven;
  2874. } else {
  2875. ulPatternEven = (ulTmpPatEven >> PatRotateRight) |
  2876. (ulTmpPatOdd << PatRotateLeft);
  2877. ulPatternOdd = (ulTmpPatOdd >> PatRotateRight) |
  2878. (ulTmpPatEven << PatRotateLeft);
  2879. }
  2880. if (StartOffset != 0) {
  2881. //
  2882. // swap even and odd
  2883. //
  2884. ulTmpPatEven = ulPatternEven;
  2885. ulPatternEven = ulPatternOdd;
  2886. ulPatternOdd = ulTmpPatEven;
  2887. }
  2888. }
  2889. #if DBG_PAT_CPY
  2890. if (DbgPatCpy >= 2)
  2891. {
  2892. DbgPrint(" PatEven = 0x%lx\n",ulPatternEven);
  2893. DbgPrint(" PatOdd = 0x%lx\n",ulPatternOdd);
  2894. }
  2895. #endif
  2896. pulScanTrg = pulTrgTmp;
  2897. ULONG cxTmp = cxDword;
  2898. //
  2899. // pulTrg = beginning of next scan line
  2900. //
  2901. //
  2902. // assign temp patterns
  2903. //
  2904. ulTmpPatEven = ulPatternEven;
  2905. ulTmpPatOdd = ulPatternOdd;
  2906. pulTrg = pulScanTrg;
  2907. if (StartCase != 0)
  2908. {
  2909. switch (StartCase)
  2910. {
  2911. case 1:
  2912. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2913. *((PUSHORT)pulTrg+1) = (SHORT)(ulTmpPatEven >> 16);
  2914. break;
  2915. case 2:
  2916. *((PUSHORT)pulTrg+1) = (SHORT)(ulTmpPatEven >> 16);
  2917. break;
  2918. case 3:
  2919. *((PBYTE)pulTrg+3) = (BYTE)(ulTmpPatEven >> 24);
  2920. break;
  2921. case 4:
  2922. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2923. break;
  2924. case 5:
  2925. *((PBYTE)pulTrg+1) = (BYTE)(ulTmpPatEven >> 8);
  2926. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2927. break;
  2928. case 6:
  2929. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2930. break;
  2931. }
  2932. pulTrg++;
  2933. //
  2934. // swap patterns
  2935. //
  2936. ulTmp = ulTmpPatEven;
  2937. ulTmpPatEven = ulTmpPatOdd;
  2938. ulTmpPatOdd = ulTmp;
  2939. }
  2940. if (cxDword > 7) {
  2941. ulffPattern[0] = ulTmpPatEven;
  2942. ulffPattern[1] = ulTmpPatOdd;
  2943. ff.culFill = cxDword;
  2944. ff.pvTrg = (PVOID)pulTrg;
  2945. vFetchAndCopy(&ff);
  2946. pulTrg += cxDword;
  2947. } else {
  2948. //
  2949. // dword pairs
  2950. //
  2951. while (cxTmp >= 2) {
  2952. *pulTrg = ulTmpPatEven;
  2953. *(pulTrg+1) = ulTmpPatOdd;
  2954. pulTrg += 2;
  2955. cxTmp -= 2;
  2956. }
  2957. //
  2958. // possible last dword
  2959. //
  2960. if (cxTmp) {
  2961. *pulTrg = ulTmpPatEven;
  2962. pulTrg++;
  2963. }
  2964. }
  2965. //
  2966. // end case if needed
  2967. //
  2968. if (EndCase != 0) {
  2969. //
  2970. // if cxDword is odd then the patterns must be swapped
  2971. //
  2972. if (cxDword & 0x01) {
  2973. ulTmpPatEven = ulTmpPatOdd;
  2974. }
  2975. switch (EndCase) {
  2976. case 1:
  2977. *(PBYTE)pulTrg = (BYTE)ulTmpPatEven;
  2978. break;
  2979. case 2:
  2980. *(PUSHORT)pulTrg = (USHORT)ulTmpPatEven;
  2981. break;
  2982. case 3:
  2983. *(PUSHORT)pulTrg = (USHORT)ulTmpPatEven;
  2984. *((PBYTE)pulTrg+2) = (BYTE)(ulTmpPatEven >> 16);
  2985. break;
  2986. }
  2987. }
  2988. //
  2989. // inc dst and pat pointers
  2990. //
  2991. pulPat = (PULONG)((PBYTE)pulPat + lDeltaPat);
  2992. if (pulPat >= pulPatMax) {
  2993. pulPat = pulPatBase;
  2994. }
  2995. pjTrgScan = pjTrgScan + ppbf->lDeltaTrg;
  2996. prow++;
  2997. } while (--crow);
  2998. }