Source code of Windows XP (NT5)
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.

743 lines
22 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: stroke.c $
  4. *
  5. * DrvStrokePath for the display driver.
  6. *
  7. * Copyright (c) 1992-1995 Microsoft Corporation
  8. * Copyright (c) 1996 Cirrus Logic, Inc.
  9. *
  10. * $Log: S:/projects/drivers/ntsrc/display/STROKE.C_V $
  11. *
  12. * Rev 1.3 10 Jan 1997 15:40:18 PLCHU
  13. *
  14. *
  15. * Rev 1.2 Nov 07 1996 16:48:06 unknown
  16. *
  17. *
  18. * Rev 1.1 Oct 10 1996 15:39:26 unknown
  19. *
  20. *
  21. * Rev 1.1 12 Aug 1996 16:55:06 frido
  22. * Removed unaccessed local variables.
  23. *
  24. * chu01 : 01-02-97 5480 BitBLT enhancement
  25. *
  26. *
  27. \******************************************************************************/
  28. #include "precomp.h"
  29. VOID (*gapfnStripMm[])(PDEV*, STRIP*, LINESTATE*) = {
  30. vMmSolidHorizontal,
  31. vMmSolidVertical,
  32. vInvalidStrip, // Diagonal
  33. vInvalidStrip, // Diagonal
  34. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  35. vMmSolidHorizontal,
  36. vMmSolidVertical,
  37. vInvalidStrip, // Diagonal
  38. vInvalidStrip, // Diagonal
  39. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  40. // solid lines, and the same number for non-solid lines:
  41. vMmStyledHorizontal,
  42. vMmStyledVertical,
  43. vInvalidStrip, // Diagonal
  44. vInvalidStrip, // Diagonal
  45. vMmStyledHorizontal,
  46. vMmStyledVertical,
  47. vInvalidStrip, // Diagonal
  48. vInvalidStrip, // Diagonal
  49. };
  50. VOID (*gapfnStripIo[])(PDEV*, STRIP*, LINESTATE*) = {
  51. vIoSolidHorizontal,
  52. vIoSolidVertical,
  53. vInvalidStrip, // Diagonal
  54. vInvalidStrip, // Diagonal
  55. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  56. vIoSolidHorizontal,
  57. vIoSolidVertical,
  58. vInvalidStrip, // Diagonal
  59. vInvalidStrip, // Diagonal
  60. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  61. // solid lines, and the same number for non-solid lines:
  62. vIoStyledHorizontal,
  63. vIoStyledVertical,
  64. vInvalidStrip, // Diagonal
  65. vInvalidStrip, // Diagonal
  66. vIoStyledHorizontal,
  67. vIoStyledVertical,
  68. vInvalidStrip, // Diagonal
  69. vInvalidStrip, // Diagonal
  70. };
  71. // chu01
  72. VOID (*gapfnPackedStripMm[])(PDEV*, STRIP*, LINESTATE*) = {
  73. vMmSolidHorizontal80,
  74. vMmSolidVertical80,
  75. vInvalidStrip, // Diagonal
  76. vInvalidStrip, // Diagonal
  77. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  78. vMmSolidHorizontal80,
  79. vMmSolidVertical80,
  80. vInvalidStrip, // Diagonal
  81. vInvalidStrip, // Diagonal
  82. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  83. // solid lines, and the same number for non-solid lines:
  84. vMmStyledHorizontal,
  85. vMmStyledVertical,
  86. vInvalidStrip, // Diagonal
  87. vInvalidStrip, // Diagonal
  88. vMmStyledHorizontal,
  89. vMmStyledVertical,
  90. vInvalidStrip, // Diagonal
  91. vInvalidStrip, // Diagonal
  92. };
  93. // Style array for alternate style (alternates one pixel on, one pixel off):
  94. STYLEPOS gaspAlternateStyle[] = { 1 };
  95. BOOL bPuntStrokePath(
  96. SURFOBJ *pso,
  97. PATHOBJ *ppo,
  98. CLIPOBJ *pco,
  99. XFORMOBJ *pxo,
  100. BRUSHOBJ *pbo,
  101. POINTL *pptlBrushOrg,
  102. LINEATTRS *plineattrs,
  103. MIX mix);
  104. /******************************Public*Routine******************************\
  105. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  106. *
  107. * Strokes the path.
  108. *
  109. \**************************************************************************/
  110. BOOL DrvStrokePath(
  111. SURFOBJ* pso,
  112. PATHOBJ* ppo,
  113. CLIPOBJ* pco,
  114. XFORMOBJ* pxo,
  115. BRUSHOBJ* pbo,
  116. POINTL* pptlBrush,
  117. LINEATTRS* pla,
  118. MIX mix)
  119. {
  120. PDEV *ppdev = (PDEV*) pso->dhpdev;
  121. DSURF *pdsurf;
  122. OH* poh;
  123. LONG cBpp;
  124. BYTE jHwRop;
  125. BYTE jMode;
  126. ULONG ulSolidColor;
  127. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  128. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  129. LINESTATE ls;
  130. PFNSTRIP* apfn;
  131. FLONG fl;
  132. RECTL arclClip[4]; // For rectangular clipping
  133. if ((mix & 0xf) != 0x0d) DISPDBG((3,"Line with mix(%x)", mix));
  134. // Pass the surface off to GDI if it's a device bitmap that we've
  135. // converted to a DIB:
  136. pdsurf = (DSURF*) pso->dhsurf;
  137. if (pdsurf->dt == DT_DIB)
  138. {
  139. return(EngStrokePath(pdsurf->pso, ppo, pco, pxo, pbo, pptlBrush,
  140. pla, mix));
  141. }
  142. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  143. // offset now so that we won't need to refer to the DSURF again:
  144. poh = pdsurf->poh;
  145. cBpp = ppdev->cBpp;
  146. ppdev->xOffset = poh->x;
  147. ppdev->yOffset = poh->y;
  148. ppdev->xyOffset = poh->xy;
  149. if ((DRIVER_PUNT_ALL) || (DRIVER_PUNT_LINES))
  150. {
  151. return bPuntStrokePath(pso,ppo,pco,pxo,pbo,pptlBrush,pla,mix);
  152. }
  153. //
  154. // Get the device ready:
  155. //
  156. jHwRop = gajHwMixFromMix[mix & 0xf];
  157. // Get the color expanded to a DWORD in the blt parameters.
  158. // replicate the color from a byte to a dword.
  159. // NOTE: this is pixel depth specific.
  160. jMode = ENABLE_COLOR_EXPAND |
  161. ENABLE_8x8_PATTERN_COPY |
  162. ppdev->jModeColor;
  163. ulSolidColor = pbo->iSolidColor;
  164. if (cBpp == 1)
  165. {
  166. ulSolidColor |= ulSolidColor << 8;
  167. ulSolidColor |= ulSolidColor << 16;
  168. }
  169. else if (cBpp == 2)
  170. {
  171. ulSolidColor |= ulSolidColor << 16;
  172. }
  173. //
  174. // chu01
  175. //
  176. if ((ppdev->flCaps & CAPS_COMMAND_LIST) && (ppdev->pCommandList != NULL))
  177. {
  178. ULONG jULHwRop ;
  179. DWORD jExtMode = 0 ;
  180. BYTE* pjBase = ppdev->pjBase ;
  181. jULHwRop = gajHwPackedMixFromMix[mix & 0xf] ;
  182. jExtMode = (ENABLE_XY_POSITION_PACKED | ENABLE_COLOR_EXPAND |
  183. ENABLE_8x8_PATTERN_COPY | ppdev->jModeColor) ;
  184. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase) ;
  185. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset) ;
  186. CP_MM_DST_Y_OFFSET(ppdev, pjBase, ppdev->lDelta) ;
  187. CP_MM_BLT_MODE_PACKED(ppdev, pjBase, jExtMode | jULHwRop) ;
  188. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor) ;
  189. }
  190. else
  191. {
  192. if (ppdev->flCaps & CAPS_MM_IO)
  193. {
  194. BYTE * pjBase = ppdev->pjBase;
  195. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  196. CP_MM_ROP(ppdev, pjBase, jHwRop);
  197. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
  198. CP_MM_DST_Y_OFFSET(ppdev, pjBase, ppdev->lDelta);
  199. CP_MM_BLT_MODE(ppdev, pjBase, jMode);
  200. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  201. }
  202. else
  203. {
  204. BYTE * pjPorts = ppdev->pjPorts;
  205. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  206. CP_IO_ROP(ppdev, pjPorts, jHwRop);
  207. CP_IO_SRC_ADDR(ppdev, pjPorts, ppdev->ulSolidColorOffset);
  208. CP_IO_DST_Y_OFFSET(ppdev, pjPorts, ppdev->lDelta);
  209. CP_IO_BLT_MODE(ppdev, pjPorts, jMode);
  210. CP_IO_FG_COLOR(ppdev, pjPorts, ulSolidColor);
  211. }
  212. }
  213. fl = 0;
  214. // Look after styling initialization:
  215. if (pla->fl & LA_ALTERNATE)
  216. {
  217. ls.cStyle = 1;
  218. ls.spTotal = 1;
  219. ls.spTotal2 = 2;
  220. ls.spRemaining = 1;
  221. ls.aspRtoL = &gaspAlternateStyle[0];
  222. ls.aspLtoR = &gaspAlternateStyle[0];
  223. ls.spNext = HIWORD(pla->elStyleState.l);
  224. ls.xyDensity = 1;
  225. fl |= FL_STYLED;
  226. ls.ulStartMask = 0L;
  227. }
  228. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  229. {
  230. PFLOAT_LONG pstyle;
  231. STYLEPOS* pspDown;
  232. STYLEPOS* pspUp;
  233. pstyle = &pla->pstyle[pla->cstyle];
  234. ls.xyDensity = STYLE_DENSITY;
  235. ls.spTotal = 0;
  236. while (pstyle-- > pla->pstyle)
  237. {
  238. ls.spTotal += pstyle->l;
  239. }
  240. ls.spTotal *= STYLE_DENSITY;
  241. ls.spTotal2 = 2 * ls.spTotal;
  242. // Compute starting style position (this is guaranteed not to overflow):
  243. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  244. LOWORD(pla->elStyleState.l);
  245. fl |= FL_STYLED;
  246. ls.cStyle = pla->cstyle;
  247. ls.aspRtoL = aspRtoL;
  248. ls.aspLtoR = aspLtoR;
  249. if (pla->fl & LA_STARTGAP)
  250. ls.ulStartMask = 0xffffffffL;
  251. else
  252. ls.ulStartMask = 0L;
  253. pstyle = pla->pstyle;
  254. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  255. pspUp = &ls.aspLtoR[0];
  256. while (pspDown >= &ls.aspRtoL[0])
  257. {
  258. *pspDown = pstyle->l * STYLE_DENSITY;
  259. *pspUp = *pspDown;
  260. pspUp++;
  261. pspDown--;
  262. pstyle++;
  263. }
  264. }
  265. // chu01
  266. if ((ppdev->flCaps & CAPS_COMMAND_LIST) && (ppdev->pCommandList != NULL))
  267. {
  268. apfn = &gapfnPackedStripMm[NUM_STRIP_DRAW_STYLES *
  269. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  270. }
  271. else if (ppdev->flCaps & CAPS_MM_IO)
  272. {
  273. apfn = &gapfnStripMm[NUM_STRIP_DRAW_STYLES *
  274. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  275. }
  276. else
  277. {
  278. apfn = &gapfnStripIo[NUM_STRIP_DRAW_STYLES *
  279. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  280. }
  281. // Set up to enumerate the path:
  282. if (pco->iDComplexity != DC_COMPLEX)
  283. {
  284. PATHDATA pd;
  285. RECTL* prclClip = (RECTL*) NULL;
  286. BOOL bMore;
  287. ULONG cptfx;
  288. POINTFIX ptfxStartFigure;
  289. POINTFIX ptfxLast;
  290. POINTFIX* pptfxFirst;
  291. POINTFIX* pptfxBuf;
  292. if (pco->iDComplexity == DC_RECT)
  293. {
  294. fl |= FL_SIMPLE_CLIP;
  295. arclClip[0] = pco->rclBounds;
  296. // FL_FLIP_D:
  297. arclClip[1].top = pco->rclBounds.left;
  298. arclClip[1].left = pco->rclBounds.top;
  299. arclClip[1].bottom = pco->rclBounds.right;
  300. arclClip[1].right = pco->rclBounds.bottom;
  301. // FL_FLIP_V:
  302. arclClip[2].top = -pco->rclBounds.bottom + 1;
  303. arclClip[2].left = pco->rclBounds.left;
  304. arclClip[2].bottom = -pco->rclBounds.top + 1;
  305. arclClip[2].right = pco->rclBounds.right;
  306. // FL_FLIP_V | FL_FLIP_D:
  307. arclClip[3].top = pco->rclBounds.left;
  308. arclClip[3].left = -pco->rclBounds.bottom + 1;
  309. arclClip[3].bottom = pco->rclBounds.right;
  310. arclClip[3].right = -pco->rclBounds.top + 1;
  311. prclClip = arclClip;
  312. }
  313. pd.flags = 0;
  314. PATHOBJ_vEnumStart(ppo);
  315. do {
  316. bMore = PATHOBJ_bEnum(ppo, &pd);
  317. cptfx = pd.count;
  318. if (cptfx == 0)
  319. {
  320. break;
  321. }
  322. if (pd.flags & PD_BEGINSUBPATH)
  323. {
  324. ptfxStartFigure = *pd.pptfx;
  325. pptfxFirst = pd.pptfx;
  326. pptfxBuf = pd.pptfx + 1;
  327. cptfx--;
  328. }
  329. else
  330. {
  331. pptfxFirst = &ptfxLast;
  332. pptfxBuf = pd.pptfx;
  333. }
  334. if (pd.flags & PD_RESETSTYLE)
  335. ls.spNext = 0;
  336. if (cptfx > 0)
  337. {
  338. if (!bLines(ppdev,
  339. pptfxFirst,
  340. pptfxBuf,
  341. (RUN*) NULL,
  342. cptfx,
  343. &ls,
  344. prclClip,
  345. apfn,
  346. fl))
  347. goto ReturnFalse;
  348. }
  349. ptfxLast = pd.pptfx[pd.count - 1];
  350. if (pd.flags & PD_CLOSEFIGURE)
  351. {
  352. if (!bLines(ppdev,
  353. &ptfxLast,
  354. &ptfxStartFigure,
  355. (RUN*) NULL,
  356. 1,
  357. &ls,
  358. prclClip,
  359. apfn,
  360. fl))
  361. goto ReturnFalse;
  362. }
  363. } while (bMore);
  364. if (fl & FL_STYLED)
  365. {
  366. // Save the style state:
  367. ULONG ulHigh;
  368. ULONG ulLow;
  369. // Masked styles don't normalize the style state. It's a good
  370. // thing to do, so let's do it now:
  371. if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
  372. ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
  373. ulHigh = ls.spNext / ls.xyDensity;
  374. ulLow = ls.spNext % ls.xyDensity;
  375. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  376. }
  377. }
  378. else
  379. {
  380. // Local state for path enumeration:
  381. BOOL bMore;
  382. union {
  383. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  384. CLIPLINE cl;
  385. } cl;
  386. fl |= FL_COMPLEX_CLIP;
  387. // We use the clip object when non-simple clipping is involved:
  388. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  389. do {
  390. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  391. if (cl.cl.c != 0)
  392. {
  393. if (fl & FL_STYLED)
  394. {
  395. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  396. + LOWORD(cl.cl.lStyleState);
  397. }
  398. if (!bLines(ppdev,
  399. &cl.cl.ptfxA,
  400. &cl.cl.ptfxB,
  401. &cl.cl.arun[0],
  402. cl.cl.c,
  403. &ls,
  404. (RECTL*) NULL,
  405. apfn,
  406. fl))
  407. goto ReturnFalse;
  408. }
  409. } while (bMore);
  410. }
  411. return(TRUE);
  412. ReturnFalse:
  413. return(FALSE);
  414. }
  415. BOOL bPuntStrokePath(
  416. SURFOBJ* pso,
  417. PATHOBJ* ppo,
  418. CLIPOBJ* pco,
  419. XFORMOBJ* pxo,
  420. BRUSHOBJ* pbo,
  421. POINTL* pptlBrush,
  422. LINEATTRS* pla,
  423. MIX mix)
  424. {
  425. PDEV* ppdev = (PDEV*) pso->dhpdev;
  426. BOOL b = TRUE;
  427. if (pso->iType == STYPE_BITMAP)
  428. {
  429. b = EngStrokePath(pso,ppo,pco,pxo,pbo,
  430. pptlBrush,pla,mix);
  431. goto ReturnStatus;
  432. }
  433. if (DIRECT_ACCESS(ppdev))
  434. {
  435. //////////////////////////////////////////////////////////////////////
  436. // Banked Framebuffer bPuntBlt
  437. //
  438. // This section of code handles a PuntBlt when GDI can directly draw
  439. // on the framebuffer, but the drawing has to be done in banks:
  440. BANK bnk;
  441. {
  442. ASSERTDD(pso->iType != STYPE_BITMAP,
  443. "Dest should be the screen");
  444. // Do a memory-to-screen blt:
  445. if (ppdev->bLinearMode)
  446. {
  447. SURFOBJ* psoPunt = ppdev->psoPunt;
  448. OH* poh = ((DSURF*) pso->dhsurf)->poh;
  449. psoPunt->pvScan0 = poh->pvScan0;
  450. ppdev->pfnBankSelectMode(ppdev, BANK_ON);
  451. b = EngStrokePath(psoPunt,ppo,pco,pxo,pbo,
  452. pptlBrush,pla,mix);
  453. goto ReturnStatus;
  454. }
  455. {
  456. RECTL rclDraw;
  457. RECTL *prclDst = &pco->rclBounds;
  458. FLOAT_LONG elSavedStyleState = pla->elStyleState;
  459. {
  460. // The bank manager requires that the 'draw' rectangle be
  461. // well-ordered:
  462. rclDraw = *prclDst;
  463. if (rclDraw.left > rclDraw.right)
  464. {
  465. rclDraw.left = prclDst->right;
  466. rclDraw.right = prclDst->left;
  467. }
  468. if (rclDraw.top > rclDraw.bottom)
  469. {
  470. rclDraw.top = prclDst->bottom;
  471. rclDraw.bottom = prclDst->top;
  472. }
  473. vBankStart(ppdev, &rclDraw, pco, &bnk);
  474. b = TRUE;
  475. do {
  476. pla->elStyleState = elSavedStyleState;
  477. b &= EngStrokePath(bnk.pso,
  478. ppo,
  479. bnk.pco,
  480. pxo,
  481. pbo,
  482. pptlBrush,
  483. pla,
  484. mix);
  485. } while (bBankEnum(&bnk));
  486. }
  487. }
  488. }
  489. goto ReturnStatus;
  490. }
  491. else
  492. {
  493. //////////////////////////////////////////////////////////////////////
  494. // Really Slow bPuntStrokePath
  495. //
  496. // Here we handle a bPuntStrokePath when GDI can't draw directly on the
  497. // framebuffer (as on the Alpha, which can't do it because of its
  498. // 32 bit bus). If you thought the banked version was slow, just
  499. // look at this one. Guaranteed, there will one bitmap
  500. // allocation and extra copy involved
  501. RECTL rclDst;
  502. RECTFX rcfxBounds;
  503. SIZEL sizl;
  504. LONG lDelta;
  505. BYTE* pjBits;
  506. BYTE* pjScan0;
  507. HSURF hsurfDst;
  508. RECTL rclScreen;
  509. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  510. rclDst.left = (rcfxBounds.xLeft >> 4);
  511. rclDst.top = (rcfxBounds.yTop >> 4);
  512. rclDst.right = (rcfxBounds.xRight >> 4) + 2;
  513. rclDst.bottom = (rcfxBounds.yBottom >> 4) + 2;
  514. //
  515. // This function is guarenteed to get a clip object. Since the
  516. // rounding of the above calculation can give us a rectangle
  517. // outside the screen area, we must clip to the drawing area.
  518. //
  519. {
  520. ASSERTDD(pco != NULL, "clip object pointer is NULL");
  521. // We have to intersect the destination rectangle with
  522. // the clip bounds if there is one (consider the case
  523. // where the app asked to blt a really, really big
  524. // rectangle from the screen -- prclDst would be really,
  525. // really big but pco->rclBounds would be the actual
  526. // area of interest):
  527. rclDst.left = max(rclDst.left, pco->rclBounds.left);
  528. rclDst.top = max(rclDst.top, pco->rclBounds.top);
  529. rclDst.right = min(rclDst.right, pco->rclBounds.right);
  530. rclDst.bottom = min(rclDst.bottom, pco->rclBounds.bottom);
  531. }
  532. sizl.cx = rclDst.right - rclDst.left;
  533. sizl.cy = rclDst.bottom - rclDst.top;
  534. // We need to create a temporary work buffer. We have to do
  535. // some fudging with the offsets so that the upper-left corner
  536. // of the (relative coordinates) clip object bounds passed to
  537. // GDI will be transformed to the upper-left corner of our
  538. // temporary bitmap.
  539. // The alignment doesn't have to be as tight as this at 16bpp
  540. // and 32bpp, but it won't hurt:
  541. lDelta = PELS_TO_BYTES(((rclDst.right + 3) & ~3L) - (rclDst.left & ~3L));
  542. // We're actually only allocating a bitmap that is 'sizl.cx' x
  543. // 'sizl.cy' in size:
  544. pjBits = ALLOC(lDelta * sizl.cy);
  545. if (pjBits == NULL)
  546. goto ReturnStatus;
  547. // We now adjust the surface's 'pvScan0' so that when GDI thinks
  548. // it's writing to pixel (rclDst.top, rclDst.left), it will
  549. // actually be writing to the upper-left pixel of our temporary
  550. // bitmap:
  551. pjScan0 = pjBits - (rclDst.top * lDelta)
  552. - PELS_TO_BYTES(rclDst.left & ~3L);
  553. ASSERTDD((((ULONG_PTR) pjScan0) & 3) == 0,
  554. "pvScan0 must be dword aligned!");
  555. // The checked build of GDI sometimes checks on blts that
  556. // prclDst->right <= pso->sizl.cx, so we lie to it about
  557. // the size of our bitmap:
  558. sizl.cx = rclDst.right;
  559. sizl.cy = rclDst.bottom;
  560. hsurfDst = (HSURF) EngCreateBitmap(
  561. sizl, // Bitmap covers rectangle
  562. lDelta, // Use this delta
  563. ppdev->iBitmapFormat, // Same colour depth
  564. BMF_TOPDOWN, // Must have a positive delta
  565. NULL); //pjScan0); // Where (0, 0) would be
  566. if ((hsurfDst == 0) ||
  567. (!EngAssociateSurface(hsurfDst, ppdev->hdevEng, 0)))
  568. {
  569. DISPDBG((0,"bPuntStrokePath - EngCreateBitmap or "
  570. "EngAssociateSurface failed"));
  571. goto Error_3;
  572. }
  573. pso = EngLockSurface(hsurfDst);
  574. if (pso == NULL)
  575. {
  576. DISPDBG((0,"bPuntStrokePath - EngLockSurface failed"));
  577. goto Error_4;
  578. }
  579. // Make sure that the rectangle we Get/Put from/to the screen
  580. // is in absolute coordinates:
  581. rclScreen.left = rclDst.left + ppdev->xOffset;
  582. rclScreen.right = rclDst.right + ppdev->xOffset;
  583. rclScreen.top = rclDst.top + ppdev->yOffset;
  584. rclScreen.bottom = rclDst.bottom + ppdev->yOffset;
  585. // It would be nice to get a copy of the destination rectangle
  586. // only when the ROP involves the destination (or when the source
  587. // is an RLE), but we can't do that. If the brush is truly NULL,
  588. // GDI will immediately return TRUE from EngBitBlt, without
  589. // modifying the temporary bitmap -- and we would proceed to
  590. // copy the uninitialized temporary bitmap back to the screen.
  591. ppdev->pfnGetBits(ppdev, pso, &rclDst, (POINTL*) &rclScreen);
  592. b = EngStrokePath(pso,ppo,pco,pxo,pbo,
  593. pptlBrush,pla,mix);
  594. ppdev->pfnPutBits(ppdev, pso, &rclScreen, (POINTL*) &rclDst);
  595. EngUnlockSurface(pso);
  596. Error_4:
  597. EngDeleteSurface(hsurfDst);
  598. Error_3:
  599. FREE(pjBits);
  600. }
  601. ReturnStatus:
  602. return(b);
  603. }