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.

633 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: patblt.cxx
  3. *
  4. * This contains the special case blting code for P, Pn, DPx and Dn rops
  5. * with solid color and patterns.
  6. *
  7. * Created: 03-Mar-1991 22:01:14
  8. * Author: Patrick Haluptzok patrickh
  9. *
  10. * Copyright (c) 1991-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. // The amount to shift cx and xDstStart left by
  14. ULONG aulShiftFormat[7] =
  15. {
  16. 0, // BMF_DEVICE
  17. 0, // BMF_1BPP
  18. 2, // BMF_4BPP
  19. 3, // BMF_8BPP
  20. 4, // BMF_16BPP
  21. 0, // BMF_24BPP
  22. 5 // BMF_32BPP
  23. };
  24. PFN_PATBLT apfnPatBlt[][3] =
  25. {
  26. { NULL, NULL, NULL },
  27. { NULL, NULL, NULL },
  28. { NULL, NULL, NULL },
  29. { vPatCpyRect8, vPatNotRect8, vPatXorRect8 },
  30. { vPatCpyRect8, vPatNotRect8, vPatXorRect8 },
  31. { vPatCpyRect8, vPatNotRect8, vPatXorRect8 },
  32. { vPatCpyRect8, vPatNotRect8, vPatXorRect8 }
  33. };
  34. ULONG aulMulFormat[] =
  35. {
  36. 0, // BMF_DEVICE
  37. 0, // BMF_1BPP
  38. 0, // BMF_4BPP
  39. 1, // BMF_8BPP
  40. 2, // BMF_16BPP
  41. 3, // BMF_24BPP
  42. 4 // BMF_32BPP
  43. };
  44. /******************************Public*Routine******************************\
  45. * vDIBSolidBlt
  46. *
  47. * This does solid color and DstInvert blts.
  48. *
  49. * History:
  50. * 03-Feb-1992 -by- Donald Sidoroff [donalds]
  51. * Improved it.
  52. *
  53. * 01-Mar-1991 -by- Patrick Haluptzok patrickh
  54. * Wrote it.
  55. \**************************************************************************/
  56. VOID vDIBSolidBlt(
  57. SURFACE *pSurfDst,
  58. RECTL *prclDst,
  59. CLIPOBJ *pco,
  60. ULONG iColor, // the index to use for color.
  61. BOOL bInvert)
  62. {
  63. PFN_SOLIDBLT pfnDibSolid;
  64. ULONG cShift; // Shift by this for format conversion
  65. ULONG ircl;
  66. PBYTE pjDstBits;
  67. LONG lDeltaDst;
  68. BOOL bMore = FALSE;
  69. BOOL bClip = FALSE;
  70. CLIPENUMRECT clenr;
  71. //ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibSo");
  72. // Set ircl to be the format of the dst surface.
  73. ircl = pSurfDst->iFormat();
  74. // Assert the world is in order for our switch
  75. ASSERTGDI((ircl >= BMF_1BPP) && (ircl <= BMF_32BPP), "ERROR GDI vDibPatBlt");
  76. // Set up cShift, pfnDibSolid, and iColor.
  77. cShift = aulShiftFormat[ircl];
  78. if (bInvert)
  79. {
  80. if (ircl == BMF_24BPP)
  81. pfnDibSolid = vSolidXorRect24;
  82. else
  83. pfnDibSolid = vSolidXorRect1;
  84. }
  85. else
  86. {
  87. if (ircl == BMF_24BPP)
  88. pfnDibSolid = vSolidFillRect24;
  89. else
  90. pfnDibSolid = vSolidFillRect1;
  91. }
  92. // Note cascaded fall through on switch to build up iColor.
  93. // Also note that 24BPP doesn't change.
  94. // Finally, note that the non-significant bits have to be masked off because
  95. // we generate Pn in the calling routine with ~.
  96. switch(ircl)
  97. {
  98. case BMF_1BPP:
  99. if ((iColor &= 1) != 0)
  100. iColor = 0xFFFFFFFF;
  101. break;
  102. case BMF_4BPP:
  103. iColor &= 0x0F;
  104. iColor = iColor | (iColor << 4);
  105. case BMF_8BPP:
  106. iColor &= 0xFF;
  107. iColor = iColor | (iColor << 8);
  108. case BMF_16BPP:
  109. iColor &= 0xFFFF;
  110. iColor = iColor | (iColor << 16);
  111. }
  112. if (pco != (CLIPOBJ *) NULL)
  113. {
  114. switch(pco->iDComplexity)
  115. {
  116. case DC_TRIVIAL:
  117. break;
  118. case DC_RECT:
  119. bClip = TRUE;
  120. clenr.c = 1;
  121. clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
  122. break;
  123. case DC_COMPLEX:
  124. bClip = TRUE;
  125. bMore = TRUE;
  126. ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,CD_ANY,CLIPOBJ_ENUM_LIMIT);
  127. break;
  128. default:
  129. RIP("ERROR: vDIBSolidBlt - bad clipping type");
  130. }
  131. }
  132. pjDstBits = (PBYTE) pSurfDst->pvScan0();
  133. lDeltaDst = pSurfDst->lDelta();
  134. if (!bClip)
  135. {
  136. (*pfnDibSolid)(
  137. prclDst,
  138. 1,
  139. pjDstBits,
  140. lDeltaDst,
  141. iColor,
  142. cShift);
  143. }
  144. else
  145. do
  146. {
  147. if (bMore)
  148. bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
  149. for (ircl = 0; ircl < clenr.c; ircl++)
  150. {
  151. PRECTL prcl = &clenr.arcl[ircl];
  152. if (prcl->left < prclDst->left)
  153. prcl->left = prclDst->left;
  154. if (prcl->right > prclDst->right)
  155. prcl->right = prclDst->right;
  156. if (prcl->top < prclDst->top)
  157. prcl->top = prclDst->top;
  158. if (prcl->bottom > prclDst->bottom)
  159. prcl->bottom = prclDst->bottom;
  160. // We check for NULL or inverted rectanges because we may get them.
  161. if ((prcl->top < prcl->bottom) &&
  162. (prcl->left < prcl->right))
  163. {
  164. (*pfnDibSolid)(
  165. prcl,
  166. 1,
  167. pjDstBits,
  168. lDeltaDst,
  169. iColor,
  170. cShift);
  171. }
  172. }
  173. } while (bMore);
  174. }
  175. /******************************Public*Routine******************************\
  176. * vDIBPatBlt
  177. *
  178. * This does pattern blts
  179. *
  180. * History:
  181. * 20-Jan-1992 -by- Donald Sidoroff [donalds]
  182. * Wrote it.
  183. \**************************************************************************/
  184. VOID vDIBPatBlt(
  185. SURFACE *pSurfDst,
  186. CLIPOBJ *pco,
  187. RECTL *prclDst,
  188. BRUSHOBJ *pbo,
  189. POINTL *pptlBrush,
  190. ULONG iMode)
  191. {
  192. PFN_PATBLT pfnPat;
  193. PATBLTFRAME pbf;
  194. CLIPENUMRECT clenr;
  195. ULONG ircl;
  196. BOOL bMore = FALSE;
  197. BOOL bClip = FALSE;
  198. ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
  199. // Set ircl to be the format of the dst surface.
  200. ircl = pSurfDst->iFormat();
  201. // Assert the world is in order for our switch
  202. ASSERTGDI((ircl >= BMF_1BPP) && (ircl <= BMF_32BPP), "ERROR GDI vDibPatBlt");
  203. // Set up pfnPat and cMul.
  204. pfnPat = apfnPatBlt[ircl][iMode];
  205. pbf.cMul = aulMulFormat[ircl];
  206. if (pco != (CLIPOBJ *) NULL)
  207. {
  208. switch(pco->iDComplexity)
  209. {
  210. case DC_TRIVIAL:
  211. break;
  212. case DC_RECT:
  213. bClip = TRUE;
  214. clenr.c = 1;
  215. clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
  216. break;
  217. case DC_COMPLEX:
  218. bClip = TRUE;
  219. bMore = TRUE;
  220. ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,CD_ANY,CLIPOBJ_ENUM_LIMIT);
  221. break;
  222. default:
  223. RIP("ERROR: vDibPatBlt - bad clipping type");
  224. }
  225. }
  226. pbf.pvTrg = pSurfDst->pvScan0();
  227. pbf.lDeltaTrg = pSurfDst->lDelta();
  228. pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat;
  229. pbf.lDeltaPat = ((EBRUSHOBJ *) pbo)->pengbrush()->lDeltaPat;
  230. pbf.cxPat = ((EBRUSHOBJ *) pbo)->pengbrush()->cxPat * pbf.cMul;
  231. pbf.cyPat = ((EBRUSHOBJ *) pbo)->pengbrush()->cyPat;
  232. pbf.xPat = pptlBrush->x * pbf.cMul;
  233. pbf.yPat = pptlBrush->y;
  234. if (!bClip)
  235. {
  236. pbf.pvObj = (PVOID) prclDst;
  237. (*pfnPat)(&pbf);
  238. }
  239. else
  240. do
  241. {
  242. if (bMore)
  243. bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
  244. for (ircl = 0; ircl < clenr.c; ircl++)
  245. {
  246. PRECTL prcl = &clenr.arcl[ircl];
  247. if (prcl->left < prclDst->left)
  248. prcl->left = prclDst->left;
  249. if (prcl->right > prclDst->right)
  250. prcl->right = prclDst->right;
  251. if (prcl->top < prclDst->top)
  252. prcl->top = prclDst->top;
  253. if (prcl->bottom > prclDst->bottom)
  254. prcl->bottom = prclDst->bottom;
  255. // We check for NULL or inverted rectanges because we may get them.
  256. if ((prcl->top < prcl->bottom) &&
  257. (prcl->left < prcl->right))
  258. {
  259. pbf.pvObj = (PVOID) prcl;
  260. (*pfnPat)(&pbf);
  261. }
  262. }
  263. } while (bMore);
  264. }
  265. /******************************Public*Routine******************************\
  266. * vDIBPatBltSrccopy8x8
  267. *
  268. * This does only SRCCOPY blts of 8x8 patterns to DIBs.
  269. * lDelta for the pattern must be exactly # of bytes per pixel * 8.
  270. *
  271. * History:
  272. * 07-Nov-1992 -by- Michael Abrash [mikeab]
  273. * Wrote it.
  274. \**************************************************************************/
  275. VOID vDIBPatBltSrccopy8x8(
  276. SURFACE *pSurfDst,
  277. CLIPOBJ *pco,
  278. RECTL *prclDst,
  279. BRUSHOBJ *pbo,
  280. POINTL *pptlBrush,
  281. PFN_PATBLT2 pfnPat)
  282. {
  283. PATBLTFRAME pbf;
  284. CLIPENUMRECT clenr;
  285. BOOL bMore;
  286. PRECTL prcl;
  287. INT ircl;
  288. // Assert this is the right sort of destination
  289. ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
  290. pbf.pvTrg = pSurfDst->pvScan0();
  291. pbf.lDeltaTrg = pSurfDst->lDelta();
  292. pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat;
  293. pbf.lDeltaPat = ((EBRUSHOBJ *) pbo)->pengbrush()->lDeltaPat;
  294. //
  295. // Force the X and Y pattern origin coordinates into the ranges 0-7 and 0-7,
  296. // so we don't have to do modulo arithmetic all over again at a lower level
  297. //
  298. pbf.xPat = pptlBrush->x & 0x07;
  299. pbf.yPat = pptlBrush->y & 0x07;
  300. if (pco == (CLIPOBJ *) NULL)
  301. {
  302. // Unclipped
  303. pbf.pvObj = (PVOID) prclDst;
  304. pfnPat(&pbf, 1);
  305. return;
  306. }
  307. else
  308. {
  309. switch(pco->iDComplexity)
  310. {
  311. case DC_TRIVIAL: // unclipped
  312. pbf.pvObj = (PVOID) prclDst;
  313. pfnPat(&pbf, 1);
  314. return;
  315. case DC_RECT: // rectangle clipped
  316. clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
  317. // Clip the destination rectangle to the clip rectangle; it's
  318. // guaranteed that the resulting rectangle will never be null
  319. if (clenr.arcl[0].left <= prclDst->left)
  320. clenr.arcl[0].left = prclDst->left;
  321. if (clenr.arcl[0].right >= prclDst->right)
  322. clenr.arcl[0].right = prclDst->right;
  323. if (clenr.arcl[0].top <= prclDst->top)
  324. clenr.arcl[0].top = prclDst->top;
  325. if (clenr.arcl[0].bottom >= prclDst->bottom)
  326. clenr.arcl[0].bottom = prclDst->bottom;
  327. if ((clenr.arcl[0].left < clenr.arcl[0].right) &&
  328. (clenr.arcl[0].top < clenr.arcl[0].bottom))
  329. {
  330. pbf.pvObj = (PVOID) clenr.arcl;
  331. pfnPat(&pbf, 1);
  332. }
  333. return;
  334. case DC_COMPLEX: // complex region clipped
  335. ((ECLIPOBJ *) pco)->cEnumStart(FALSE,
  336. CT_RECTANGLES,
  337. CD_ANY,
  338. CLIPOBJ_ENUM_LIMIT);
  339. do
  340. {
  341. // Get the next batch of rectangles in the clip region
  342. bMore =
  343. ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
  344. // If there are any rectangles in this enumeration, clip the
  345. // destination rectangle to each clip region rectangle, then
  346. // fill all the rectangles at once
  347. if (clenr.c > 0)
  348. {
  349. // Clip the rectangles
  350. for (ircl = 0, prcl = clenr.arcl; ircl < (INT) clenr.c;
  351. ircl++, prcl++)
  352. {
  353. if (prcl->left < prclDst->left)
  354. prcl->left = prclDst->left;
  355. if (prcl->right > prclDst->right)
  356. prcl->right = prclDst->right;
  357. if (prcl->top < prclDst->top)
  358. prcl->top = prclDst->top;
  359. if (prcl->bottom > prclDst->bottom)
  360. prcl->bottom = prclDst->bottom;
  361. //
  362. // make sure rectangle is not inverted,
  363. // this can happen for single scan line
  364. // clip regions clipped to dst. If found,
  365. // set to NULL rectangle
  366. //
  367. if (prcl->right < prcl->left)
  368. {
  369. prcl->right = prcl->left;
  370. }
  371. if (prcl->bottom < prcl->top)
  372. {
  373. prcl->bottom = prcl->top;
  374. }
  375. }
  376. // Draw the rectangles
  377. pbf.pvObj = (PVOID) clenr.arcl;
  378. pfnPat(&pbf, (INT) clenr.c);
  379. }
  380. } while (bMore);
  381. return;
  382. default:
  383. RIP("ERROR: vDIBPatBltSrccopy8x8 - bad clipping type");
  384. }
  385. }
  386. }
  387. /******************************Public*Routine******************************\
  388. * vDIBnPatBltSrccopy6x6
  389. *
  390. * This does SRCCOPY pattern blts to 6x6 4-bpp DIBs and 1-bpp DIBs.
  391. * lDelta for the pattern must be exactly 6 pixels (4 bytes).
  392. *
  393. * History:
  394. * 07-Nov-1992 -by- Michael Abrash [mikeab]
  395. * Wrote it.
  396. *
  397. * 17-Nov-1992 -by- Stephen Estrop [StephenE]
  398. * Made it take a pointer to a
  399. \**************************************************************************/
  400. VOID vDIBnPatBltSrccopy6x6(
  401. SURFACE *pSurfDst,
  402. CLIPOBJ *pco,
  403. RECTL *prclDst,
  404. BRUSHOBJ *pbo,
  405. POINTL *pptlBrush,
  406. PFN_PATBLT2 pfnPatBlt)
  407. {
  408. PATBLTFRAME pbf;
  409. CLIPENUMRECT clenr;
  410. BOOL bMore;
  411. PRECTL prcl;
  412. ULONG ircl;
  413. // Assert this is the right sort of destination
  414. ASSERTGDI(pSurfDst->iType() == STYPE_BITMAP, "ERROR GDI vDibPat");
  415. pbf.pvTrg = pSurfDst->pvScan0();
  416. pbf.lDeltaTrg = pSurfDst->lDelta();
  417. pbf.pvPat = (PVOID) ((EBRUSHOBJ *) pbo)->pengbrush()->pjPat;
  418. // Force the X and Y pattern origin coordinates into the ranges 0-5 and 0-5,
  419. // so we don't have to do modulo arithmetic all over again at a lower level
  420. if (pptlBrush->x >= 0)
  421. pbf.xPat = pptlBrush->x % 0x06;
  422. else
  423. pbf.xPat = (6 - 1) - ((-pptlBrush->x - 1) % 6);
  424. if (pptlBrush->y >= 0)
  425. pbf.yPat = pptlBrush->y % 0x06;
  426. else
  427. pbf.yPat = (6 - 1) - ((-pptlBrush->y - 1) % 6);
  428. if (pco == (CLIPOBJ *) NULL)
  429. {
  430. // Unclipped
  431. pbf.pvObj = (PVOID) prclDst;
  432. (*pfnPatBlt)(&pbf, 1);
  433. return;
  434. }
  435. else
  436. {
  437. switch(pco->iDComplexity)
  438. {
  439. case DC_TRIVIAL: // unclipped
  440. pbf.pvObj = (PVOID) prclDst;
  441. (*pfnPatBlt)(&pbf, 1);
  442. return;
  443. case DC_RECT: // rectangle clipped
  444. clenr.arcl[0] = pco->rclBounds; // Use acclerator for clipping
  445. // Clip the destination rectangle to the clip rectangle
  446. if (clenr.arcl[0].left <= prclDst->left)
  447. clenr.arcl[0].left = prclDst->left;
  448. if (clenr.arcl[0].right >= prclDst->right)
  449. clenr.arcl[0].right = prclDst->right;
  450. if (clenr.arcl[0].top <= prclDst->top)
  451. clenr.arcl[0].top = prclDst->top;
  452. if (clenr.arcl[0].bottom >= prclDst->bottom)
  453. clenr.arcl[0].bottom = prclDst->bottom;
  454. if ((clenr.arcl[0].left < clenr.arcl[0].right) &&
  455. (clenr.arcl[0].top < clenr.arcl[0].bottom))
  456. {
  457. pbf.pvObj = (PVOID) clenr.arcl;
  458. (*pfnPatBlt)(&pbf, 1);
  459. }
  460. return;
  461. case DC_COMPLEX: // complex region clipped
  462. ((ECLIPOBJ *) pco)->cEnumStart(FALSE,
  463. CT_RECTANGLES,
  464. CD_ANY,
  465. CLIPOBJ_ENUM_LIMIT);
  466. do
  467. {
  468. // Get the next batch of rectangles in the clip region
  469. bMore =
  470. ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
  471. // If there are any rectangles in this enumeration, clip the
  472. // destination rectangle to each clip region rectangle, then
  473. // fill all the rectangles at once
  474. if (clenr.c > 0)
  475. {
  476. // Clip the rectangles
  477. for (ircl = 0, prcl = clenr.arcl; ircl < clenr.c;
  478. ircl++, prcl++)
  479. {
  480. if (prcl->left < prclDst->left)
  481. prcl->left = prclDst->left;
  482. if (prcl->right > prclDst->right)
  483. prcl->right = prclDst->right;
  484. if (prcl->top < prclDst->top)
  485. prcl->top = prclDst->top;
  486. if (prcl->bottom > prclDst->bottom)
  487. prcl->bottom = prclDst->bottom;
  488. }
  489. // Draw the rectangles
  490. pbf.pvObj = (PVOID) clenr.arcl;
  491. (*pfnPatBlt)(&pbf, clenr.c);
  492. }
  493. } while (bMore);
  494. return;
  495. default:
  496. RIP("ERROR: vDIBnSrccopyPatBlt - bad clipping type");
  497. }
  498. }
  499. }
  500.