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.

773 lines
22 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: clipobj.cxx
  3. *
  4. * Clipping object non-inline methods
  5. *
  6. * Created: 15-Sep-1990 15:25:02
  7. * Author: Donald Sidoroff [donalds]
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. /******************************Public*Routine******************************\
  13. * XCLIPOBJ::vSetup
  14. *
  15. * Create an XCLIPOBJ.
  16. *
  17. * input:
  18. *
  19. * prgn_ - region to build clipobj from
  20. * erclExcl - Only intrested in the part of the region that intersects this
  21. * iForcedClip - CLIP_NOFORCE - will be trivial if erclExcl is fully bounded
  22. * CLIP_FORCE - will never be trivial
  23. * CLIP_NOFORCETRIV - will be trivial if single rectangle
  24. *
  25. * output/clipobj:
  26. *
  27. * iUniq - iUniq from region
  28. *
  29. * rclBounds - bounds of the clipping area
  30. * intersection of erclExcl and region bounds. It may further
  31. * be reduced to only bound rectangles that touch erclExcl.
  32. *
  33. * iDComplexity - complexity of part of region that intersects drawing
  34. *
  35. * TRIVIAL - all parts of erclExcl are visible. The object may
  36. * span multiple scans but is fully contained.
  37. *
  38. * RECT - The object (bounded by erclExcl) need only be clipped
  39. * against a single rectangle set in rclBounds.
  40. *
  41. * COMPLEX - enumeration is needed to get a list of rectangles to clip against
  42. *
  43. * iFComplexity - full region complexity, RECT, RECT4, COMPLEX
  44. *
  45. * iMode - TC_RECTANGLES - internal storage mode
  46. *
  47. * fjOptions - OC_RESERVED - this bit used to be called OC_BANK_CLIP and
  48. * is set by banking drivers. This bit has been obsoleted,
  49. * but because 4.0 drivers may still set the bit we can't
  50. * re-use it for something else.
  51. *
  52. *
  53. * hidden fields:
  54. *
  55. * cObj - number of rectangles that intersect erclExcl
  56. *
  57. * History:
  58. * 06-Oct-1993 -by- Eric Kutter [erick]
  59. * Update documentation, remove traps, add paths
  60. *
  61. * 24-Jul-1991 -by- Donald Sidoroff [donalds]
  62. * Updated to DDI spec.
  63. *
  64. * 15-Sep-1990 -by- Donald Sidoroff [donalds]
  65. * Wrote it.
  66. \**************************************************************************/
  67. #define CMAXOBJ 10
  68. VOID XCLIPOBJ::vSetup(REGION *prgn_, ERECTL& erclExcl, int iForcedClip)
  69. {
  70. // Set up the internal fields
  71. prgn = prgn_;
  72. // Initialize as many of the CLIPOBJ fields as we can:
  73. *((ULONG*)&iDComplexity) = 0; // iDComplexity = DC_TRIVIAL,
  74. // iMode = TC_RECTANGLES,
  75. // fjOptions = 0,
  76. // iFComplexity = invalid
  77. rclBounds.bottom = erclExcl.bottom;
  78. rclBounds.right = erclExcl.right;
  79. rclBounds.top = erclExcl.top;
  80. rclBounds.left = erclExcl.left;
  81. iUniq = prgn->iUnique;
  82. if ((prgn->sizeRgn <= SINGLE_REGION_SIZE) &&
  83. (rclBounds.left >= prgn->rcl.left) &&
  84. (rclBounds.top >= prgn->rcl.top) &&
  85. (rclBounds.right <= prgn->rcl.right) &&
  86. (rclBounds.bottom <= prgn->rcl.bottom) &&
  87. (iForcedClip != CLIP_FORCE))
  88. {
  89. // Unfortunately, some callers may give us an empty or crossed
  90. // 'erclExcl', and we have to watch for that case:
  91. if ((rclBounds.top < rclBounds.bottom) &&
  92. (rclBounds.left < rclBounds.right))
  93. {
  94. // This is the trivial acceptance case, which will be the most common
  95. // case. The region is a single rectangle that bounds the drawing.
  96. // We've already set up for trivial clipping.
  97. return;
  98. }
  99. }
  100. // Calculate the intersection of the drawing bounds with the region
  101. // bounds:
  102. rclBounds.left = max(rclBounds.left, prgn->rcl.left);
  103. rclBounds.top = max(rclBounds.top, prgn->rcl.top);
  104. rclBounds.right = min(rclBounds.right, prgn->rcl.right);
  105. rclBounds.bottom = min(rclBounds.bottom, prgn->rcl.bottom);
  106. if ((rclBounds.left >= rclBounds.right) ||
  107. (rclBounds.top >= rclBounds.bottom))
  108. {
  109. // This takes care of the trivial rejection case. It is the caller's
  110. // responsibility to again check for this case by calling 'bEmpty'
  111. // on 'rclBounds' -- in which case, we have to collapse the rectangle:
  112. rclBounds.left = rclBounds.right;
  113. return;
  114. }
  115. if ((prgn->sizeRgn <= SINGLE_REGION_SIZE) &&
  116. (iForcedClip != CLIP_FORCE))
  117. {
  118. // If the region is a single rectangle, the region bound IS the
  119. // region, so we're done. Note that the trivial rejection case
  120. // may come through this case -- it's the caller's responsibility
  121. // to check that the rectangle is not empty.
  122. if (iForcedClip != CLIP_NOFORCETRIV)
  123. iDComplexity = DC_RECT;
  124. return;
  125. }
  126. // Darn, now we have to do some real work.
  127. ERECTL *percl = (ERECTL *) &rclBounds;
  128. cObjs = 0; // Initialize object count
  129. if (prgn->sizeRgn > QUANTUM_REGION_SIZE)
  130. iFComplexity = FC_COMPLEX;
  131. else
  132. if (prgn->sizeRgn > SINGLE_REGION_SIZE)
  133. iFComplexity = FC_RECT4;
  134. // Traverse the scans
  135. ERECTL erclAcc(0, 0, 0, 0); // Accumulate segments here
  136. PSCAN pscn = prgn->pscnHead();
  137. COUNT cScan = prgn->cScans;
  138. COUNT iWall;
  139. BOOL bSimple = (iForcedClip != CLIP_FORCE); // Assume DC_TRIVIAL clipping unless forced
  140. COUNT cHit = 0;
  141. // find the first one inside
  142. while (cScan && (percl->top >= pscn->yBottom))
  143. {
  144. pscn = pscnGet(pscn);
  145. --cScan;
  146. }
  147. while (cScan--)
  148. {
  149. if (pscn->yTop >= percl->bottom) // Have we passed the rectangle?
  150. break;
  151. BOOL bBounded = FALSE; // Assume rectangle is unbounded
  152. for (iWall = 0; iWall != pscn->cWalls; iWall += 2)
  153. {
  154. // If the right edge of the segment is to the left of the rectangle
  155. // advance to the next scan segment and test again.
  156. if (pscn->ai_x[iWall + 1].x <= percl->left)
  157. continue;
  158. // If the left edge of the segment is to the right of the rectangle
  159. // goto the next scan.
  160. if (pscn->ai_x[iWall].x >= percl->right)
  161. break;
  162. // Increment count of objects
  163. cObjs++;
  164. // this is getting rediculous, we assume it is complex
  165. if (cObjs >= CMAXOBJ)
  166. {
  167. iDComplexity = DC_COMPLEX;
  168. cObjs = (COUNT)-1;
  169. return;
  170. }
  171. // OK, we now know that SOME part of the rectangle overlaps
  172. // this scan segment. Find the overlap and accumulate it.
  173. RECTL rclTmp;
  174. rclTmp.left = pscn->ai_x[iWall].x;
  175. rclTmp.right = pscn->ai_x[iWall + 1].x;
  176. rclTmp.top = pscn->yTop;
  177. rclTmp.bottom = pscn->yBottom;
  178. erclAcc += rclTmp; // Expand the accumlated rectangle
  179. // Now see if this rectangle peeks out past the segment. If
  180. // it doesn't, then we still might be simply clipped.
  181. if ((percl->left >= pscn->ai_x[iWall].x) &&
  182. (percl->right <= pscn->ai_x[iWall + 1].x))
  183. {
  184. bBounded = TRUE;
  185. }
  186. }
  187. // If the rectangle was not left/right bounded by some segment in
  188. // the scan, then this can't be a simple clip case.
  189. bSimple &= bBounded;
  190. pscn = pscnGet(pscn);
  191. }
  192. // Clip the exclusion rectangle against the accumulated rectangle
  193. *percl *= erclAcc;
  194. if (!bSimple)
  195. {
  196. iDComplexity = (BYTE)(cObjs == 1 ? DC_RECT : DC_COMPLEX);
  197. }
  198. else
  199. {
  200. if ((iForcedClip == CLIP_NOFORCE) && !percl->bEqual(erclExcl))
  201. iDComplexity = DC_RECT;
  202. }
  203. }
  204. /******************************Public*Routine******************************\
  205. * ULONG XCLIPOBJ::cEnumStart(bAll, iType, iDir, cLimit)
  206. *
  207. * Set up the enumerator for the clipping object
  208. *
  209. * History:
  210. * 24-Jul-1991 -by- Donald Sidoroff [donalds]
  211. * Updated to DDI spec.
  212. *
  213. * 19-Sep-1990 -by- Donald Sidoroff [donalds]
  214. * Wrote it.
  215. \**************************************************************************/
  216. extern "C" ULONG CLIPOBJ_cEnumStart(
  217. CLIPOBJ *pco,
  218. BOOL bAll,
  219. ULONG iType,
  220. ULONG iDir,
  221. ULONG cLimit)
  222. {
  223. return (*(XCLIPOBJ *)pco).cEnumStart(bAll, iType, iDir, cLimit);
  224. }
  225. ULONG XCLIPOBJ::cEnumStart(
  226. BOOL bAll,
  227. ULONG iType,
  228. ULONG iDir,
  229. ULONG cLimit)
  230. {
  231. // We may need to merge trapezoid region with the bounding rect if the flag
  232. // indicate so.
  233. // Handle any old direction requests
  234. if (iDir == CD_ANY)
  235. iDir = CD_RIGHTDOWN;
  236. // Save the info in the enumerator
  237. enmr.iType = iType;
  238. enmr.iDir = iDir;
  239. enmr.bAll = bAll;
  240. // If we are enumerating the entire region, use the region bounding box
  241. // otherwise use the exclusion rectangle
  242. if (enmr.bAll)
  243. enmr.ercl = *((ERECTL *) &prgn->rcl);
  244. else
  245. {
  246. enmr.ercl = *((ERECTL *) &rclBounds);
  247. }
  248. // Now we have to do some actual work
  249. // Set up top to bottom info
  250. enmr.cScans = prgn->cScans - 1;
  251. enmr.yCurr = 0;
  252. enmr.yFinal = 0;
  253. // Start from the top or bottom? Also, find the scan before the first scan
  254. // that intersects the rclBounds. By finding the previous scan, we can let
  255. // the normal enumeration find the first wall.
  256. PSCAN pscn1;
  257. if (iDir < CD_RIGHTUP)
  258. {
  259. // top to bottom
  260. enmr.pscn = prgn->pscnHead();
  261. enmr.yDelta = 1;
  262. if (!enmr.bAll)
  263. {
  264. pscn1 = pscnGet(enmr.pscn);
  265. while (pscn1->yBottom <= enmr.ercl.top)
  266. {
  267. --enmr.cScans;
  268. if (enmr.cScans == 0)
  269. return((ULONG)-1);
  270. enmr.pscn = pscn1;
  271. pscn1 = pscnGet(pscn1);
  272. }
  273. }
  274. }
  275. else
  276. {
  277. // bottom to top
  278. enmr.pscn = pscnGot(prgn->pscnTail);
  279. enmr.yDelta = -1;
  280. if (!enmr.bAll)
  281. {
  282. pscn1 = pscnGot(enmr.pscn);
  283. while (pscn1->yTop >= enmr.ercl.bottom)
  284. {
  285. --enmr.cScans;
  286. if (enmr.cScans == 0)
  287. return((ULONG)-1);
  288. enmr.pscn = pscn1;
  289. pscn1 = pscnGot(pscn1);
  290. }
  291. }
  292. }
  293. // Left to right info
  294. enmr.iWall = 0;
  295. enmr.iFinal = 0;
  296. // Going left or right?
  297. if (iDir & 1)
  298. enmr.iOff = (COUNT) -2;
  299. else
  300. enmr.iOff = 2;
  301. if (enmr.bAll)
  302. return(cObjs <= cLimit ? cObjs : (ULONG) -1);
  303. return((ULONG) -1);
  304. }
  305. /******************************Public*Routine******************************\
  306. * ULONG XCLIPOBJ::cEnum(cj, pv)
  307. *
  308. * Get the next batch of rectangles or trapezoids from the clipping object
  309. *
  310. * History:
  311. * 24-Jul-1991 -by- Donald Sidoroff [donalds]
  312. * Updated to DDI spec.
  313. *
  314. * 15-Sep-1990 -by- Donald Sidoroff [donalds]
  315. * Wrote it.
  316. \**************************************************************************/
  317. extern "C" BOOL CLIPOBJ_bEnum(CLIPOBJ* pco, ULONG cj, ULONG *pv)
  318. {
  319. return (*(XCLIPOBJ *)pco).bEnum(cj, (VOID *)pv);
  320. }
  321. BOOL XCLIPOBJ::bEnum(ULONG cj,PVOID pv,ULONG *pcjFilled)
  322. {
  323. // Good old rectangle to rectangle enumeration
  324. ENUMRECTS *penrc = (ENUMRECTS *) pv;
  325. RECTL *prcl = penrc->arcl;
  326. if (cj < sizeof(ENUMRECTS))
  327. {
  328. if (pcjFilled)
  329. *pcjFilled = 0;
  330. return FALSE;
  331. }
  332. cj -= offsetof(ENUMRECTS,arcl);
  333. if (pcjFilled)
  334. *pcjFilled = offsetof(ENUMRECTS,arcl);
  335. penrc->c = 0;
  336. if (enmr.bAll)
  337. {
  338. ULONG const RightToLeft = enmr.iDir & 1;
  339. ULONG const TopToBottom = enmr.iDir < CD_RIGHTUP;
  340. ULONG RectsWanted = cj / sizeof(RECTL);
  341. PSCAN pCurrentScan = enmr.pscn;
  342. COUNT CurrentWall = enmr.iWall;
  343. COUNT FinalWall = enmr.iFinal;
  344. int long Offset = enmr.iOff;
  345. while (enmr.cScans)
  346. {
  347. if (CurrentWall == FinalWall)
  348. {
  349. // go to the next scan
  350. if (TopToBottom)
  351. pCurrentScan = pscnGet(pCurrentScan);
  352. else
  353. pCurrentScan = pscnGot(pCurrentScan);
  354. enmr.cScans--;
  355. if(!pCurrentScan->cWalls)
  356. {
  357. continue;
  358. }
  359. if (RightToLeft)
  360. {
  361. CurrentWall = pCurrentScan->cWalls - 2;
  362. FinalWall = (COUNT) -2;
  363. }
  364. else
  365. {
  366. CurrentWall = 0;
  367. FinalWall = pCurrentScan->cWalls;
  368. }
  369. }
  370. prcl->left = pCurrentScan->ai_x[CurrentWall].x;
  371. prcl->right = pCurrentScan->ai_x[CurrentWall + 1].x;
  372. prcl->top = pCurrentScan->yTop;
  373. prcl->bottom = pCurrentScan->yBottom;
  374. CurrentWall += Offset;
  375. prcl++;
  376. penrc->c++;
  377. --RectsWanted;
  378. if (pcjFilled)
  379. *pcjFilled += sizeof(RECTL);
  380. if (!RectsWanted)
  381. {
  382. // this is the only time we need to save state, no?
  383. enmr.iWall = CurrentWall;
  384. enmr.iFinal = FinalWall;
  385. enmr.pscn = pCurrentScan;
  386. return(TRUE);
  387. }
  388. }
  389. }
  390. else // and the not all case
  391. {
  392. ERECTL erclSrc;
  393. erclSrc.top = enmr.pscn->yTop; // Reset source top
  394. erclSrc.bottom = enmr.pscn->yBottom; // and bottom
  395. while (enmr.cScans)
  396. {
  397. // do we need a new scan?
  398. if (enmr.iWall == enmr.iFinal)
  399. {
  400. // go to the next scan and see if we are done
  401. if (enmr.iDir < CD_RIGHTUP)
  402. {
  403. // top to bottom
  404. if (enmr.pscn->yBottom >= enmr.ercl.bottom)
  405. {
  406. enmr.cScans = 0;
  407. break;
  408. }
  409. enmr.pscn = pscnGet(enmr.pscn);
  410. }
  411. else
  412. {
  413. // bottom to top
  414. if (enmr.pscn->yTop <= enmr.ercl.top)
  415. {
  416. enmr.cScans = 0;
  417. break;
  418. }
  419. enmr.pscn = pscnGot(enmr.pscn);
  420. }
  421. enmr.cScans--;
  422. // setup the scan
  423. erclSrc.top = enmr.pscn->yTop; // Reset source top
  424. erclSrc.bottom = enmr.pscn->yBottom; // and bottom
  425. // find the first rectangle within the scan
  426. if (enmr.iDir & 1)
  427. {
  428. // right to left
  429. enmr.iWall = enmr.pscn->cWalls - 2;
  430. enmr.iFinal = (COUNT) -2;
  431. while ((enmr.iWall != -2) &&
  432. (enmr.pscn->ai_x[enmr.iWall].x >= enmr.ercl.right))
  433. {
  434. enmr.iWall -= 2;
  435. }
  436. }
  437. else
  438. {
  439. // left to right
  440. enmr.iWall = 0;
  441. enmr.iFinal = enmr.pscn->cWalls;
  442. while ((enmr.iWall != enmr.iFinal) &&
  443. (enmr.pscn->ai_x[enmr.iWall+1].x <= enmr.ercl.left))
  444. {
  445. enmr.iWall += 2;
  446. }
  447. }
  448. continue;
  449. }
  450. // get the left and right from the scan
  451. erclSrc.left = enmr.pscn->ai_x[enmr.iWall].x;
  452. erclSrc.right = enmr.pscn->ai_x[enmr.iWall + 1].x;
  453. // intersect the side walls. If the rectangles don't overlap, we
  454. // are done with this scan.
  455. prcl->left = max(enmr.ercl.left,erclSrc.left);
  456. prcl->right = min(enmr.ercl.right,erclSrc.right);
  457. if (prcl->left >= prcl->right)
  458. {
  459. enmr.iWall = enmr.iFinal;
  460. continue;
  461. }
  462. // compute the top and bottom - these should be moved out of inner loop(erick)
  463. prcl->top = max(enmr.ercl.top,erclSrc.top);
  464. prcl->bottom = min(enmr.ercl.bottom,erclSrc.bottom);
  465. ASSERTGDI(prcl->top < prcl->bottom,"CLIPOBJ_benum, top >= bottom\n");
  466. // advance to the next rectangle
  467. enmr.iWall += enmr.iOff;
  468. prcl++;
  469. cj -= sizeof(RECTL);
  470. if (pcjFilled)
  471. *pcjFilled += sizeof(RECTL);
  472. penrc->c++;
  473. if (cj < sizeof(RECTL))
  474. return(TRUE);
  475. }
  476. }
  477. return(FALSE);
  478. }
  479. /******************************Public*Routine******************************\
  480. * PATHOBJ *XCLIPOBJ::ppoGetPath()
  481. *
  482. * Create PATHOBJ from the clipping region.
  483. *
  484. * NOTE: This does NOT take the multi-monitor offset into account, so this
  485. * may not be used by display drivers.
  486. *
  487. * History:
  488. * 09-Mar-1992 -by- Donald Sidoroff [donalds]
  489. * Wrote it.
  490. \**************************************************************************/
  491. extern "C" PATHOBJ *CLIPOBJ_ppoGetPath(CLIPOBJ *pco)
  492. {
  493. return (*(XCLIPOBJ*)pco).ppoGetPath();
  494. }
  495. PATHOBJ *XCLIPOBJ::ppoGetPath()
  496. {
  497. // Allocate a PATHOBJ from the heap. We will free this memory only if
  498. // this function fails. Otherwise, we will rely on the device driver to
  499. // call EngDeletePath later on to free the memory.
  500. PVOID pepo = PALLOCNOZ(sizeof(EPATHOBJ),'oppG');
  501. if (pepo == (PVOID) NULL)
  502. {
  503. return((PATHOBJ *) NULL);
  504. }
  505. // Sigh, we have to create a path for this region.
  506. PATHMEMOBJ pmo;
  507. if (!pmo.bValid())
  508. {
  509. VFREEMEM(pepo);
  510. return(NULL);
  511. }
  512. EXFORMOBJ exo(IDENTITY);
  513. ASSERTGDI(exo.bValid(), "Invalid Identity transform");
  514. {
  515. // pmoRect will contain an intermediate rectangular path that will
  516. // in turn be processed into a diagonalized path that will be
  517. // contained in pmo.
  518. RTP_PATHMEMOBJ pmoRect;
  519. if
  520. (
  521. !pmoRect.bValid() ||
  522. !bCreate(pmoRect, &exo) ||
  523. !pmoRect.bDiagonalizePath(&pmo)
  524. )
  525. {
  526. VFREEMEM(pepo);
  527. return(NULL);
  528. }
  529. // pmoRect passes out of scope. Since I have NOT called
  530. // pmoRect.vKeepIt() the memory of the rectangular path will
  531. // be freed, while the diagonalized path as embodied in pmo
  532. // will live on.
  533. }
  534. // OK, nothing can fail now. We will keep the diagonalized path
  535. // by marking it as permanent. We will allow the destructor to
  536. // kill the rectangular path in pmo.
  537. pmo.vKeepIt();
  538. // Make sure we copy the accelerator fields to the path we'll be
  539. // giving out:
  540. *((EPATHOBJ*) pepo) = pmo;
  541. // Now lock down the object and point our path to it:
  542. ((EPATHOBJ *) pepo)->vLock(pmo.hpath());
  543. return((PATHOBJ *) pepo);
  544. }
  545. /******************************Public*Routine******************************\
  546. * VOID XCLIPOBJ::vFindScan(prcl, y)
  547. *
  548. * Search for the scan that contains the given point
  549. *
  550. * History:
  551. * 13-Aug-1992 -by- Donald Sidoroff [donalds]
  552. * Wrote it.
  553. \**************************************************************************/
  554. VOID XCLIPOBJ::vFindScan(
  555. RECTL *prcl,
  556. LONG y)
  557. {
  558. if (y < enmr.pscn->yTop)
  559. {
  560. while (y < enmr.pscn->yTop)
  561. enmr.pscn = pscnGot(enmr.pscn);
  562. prcl->top = max(enmr.pscn->yTop, rclBounds.top);
  563. prcl->bottom = min(enmr.pscn->yBottom, rclBounds.bottom);
  564. prcl->left = prcl->right;
  565. if (prcl->top >= prcl->bottom)
  566. prcl->top = NEG_INFINITY;
  567. if (prcl->top == NEG_INFINITY)
  568. prcl->bottom = NEG_INFINITY;
  569. }
  570. else if (y >= enmr.pscn->yBottom)
  571. {
  572. while (y >= enmr.pscn->yBottom)
  573. enmr.pscn = pscnGet(enmr.pscn);
  574. prcl->top = max(enmr.pscn->yTop, rclBounds.top);
  575. prcl->bottom = min(enmr.pscn->yBottom, rclBounds.bottom);
  576. prcl->left = prcl->right;
  577. if (prcl->top >= prcl->bottom)
  578. prcl->bottom = POS_INFINITY;
  579. if (prcl->bottom == POS_INFINITY)
  580. prcl->top = POS_INFINITY;
  581. }
  582. }
  583. /******************************Public*Routine******************************\
  584. * VOID XCLIPOBJ::vFindSegment(prcl, x, y)
  585. *
  586. * Search for the segment in the current scan that contains the given point
  587. *
  588. * History:
  589. * 13-Aug-1992 -by- Donald Sidoroff [donalds]
  590. * Wrote it.
  591. \**************************************************************************/
  592. VOID XCLIPOBJ::vFindSegment(
  593. RECTL *prcl,
  594. LONG x,
  595. LONG y)
  596. {
  597. DONTUSE(y);
  598. COUNT iWall;
  599. LONG xLeft;
  600. LONG xRight;
  601. for (iWall = 0; iWall != enmr.pscn->cWalls; iWall += 2)
  602. {
  603. if ((x >= enmr.pscn->ai_x[iWall].x) &&
  604. (x < enmr.pscn->ai_x[iWall + 1].x))
  605. {
  606. xLeft = max(enmr.pscn->ai_x[iWall].x, rclBounds.left);
  607. xRight = min(enmr.pscn->ai_x[iWall + 1].x, rclBounds.right);
  608. if (xLeft < xRight)
  609. {
  610. prcl->left = xLeft;
  611. prcl->right = xRight;
  612. }
  613. return;
  614. }
  615. }
  616. }