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.

2508 lines
102 KiB

  1. #include "precomp.h"
  2. //
  3. // BA.C
  4. // Bounds Accumulation, disply driver side
  5. //
  6. // Copyright(c) Microsoft 1997-
  7. //
  8. //
  9. //
  10. // BA_DDProcessRequest() - see ba.h
  11. //
  12. //
  13. BOOL BA_DDProcessRequest
  14. (
  15. DWORD fnEscape,
  16. LPOSI_ESCAPE_HEADER pRequest,
  17. DWORD cbRequest,
  18. LPOSI_ESCAPE_HEADER pResult,
  19. DWORD cbResult
  20. )
  21. {
  22. BOOL rc = TRUE;
  23. LPBA_BOUNDS_INFO pBoundsInfo;
  24. UINT i;
  25. RECT rect;
  26. DebugEntry(BA_DDProcessRequest);
  27. if ((cbRequest != sizeof(BA_BOUNDS_INFO)) ||
  28. (cbResult != sizeof(BA_BOUNDS_INFO)))
  29. {
  30. ERROR_OUT(("BA_DDProcessRequest: Invalid sizes %d, %d for BA_ESC", cbRequest, cbResult));
  31. rc = FALSE;
  32. DC_QUIT;
  33. }
  34. switch (fnEscape)
  35. {
  36. case BA_ESC_GET_BOUNDS:
  37. {
  38. //
  39. // The share core is calling us to get the current bounds
  40. // (presumably to try to send them). While the share core is
  41. // processing the bounds, we reset the bounds, but take a copy
  42. // first to use for spoiling orders by SDA. When the share
  43. // core has completed processing the bounds, it will call us
  44. // again with a BA_ESC_RETURN_BOUNDS escape (even if it has
  45. // sent all the bounds).
  46. //
  47. // So, we have to:
  48. // - return the bounds to the share core
  49. // - set up the spoiling rects to be these bounds
  50. // - clear our main bounds.
  51. //
  52. //
  53. // This will copy the current bounds to the caller's buffer and
  54. // clear our current bounds.
  55. // NOTE: We keep these in globals because the caller will shortly
  56. // call us to return any unsent bounds rects.
  57. //
  58. BA_CopyBounds(g_baSpoilingRects, &g_baNumSpoilingRects, TRUE);
  59. //
  60. // Return the bounds info to the share core
  61. //
  62. TRACE_OUT(( "Returning %d rects to share core", g_baNumSpoilingRects));
  63. pBoundsInfo = (LPBA_BOUNDS_INFO)pResult;
  64. pBoundsInfo->numRects = g_baNumSpoilingRects;
  65. for (i = 0; i < g_baNumSpoilingRects; i++)
  66. {
  67. RECT_TO_RECTL(&g_baSpoilingRects[i], &pBoundsInfo->rects[i]);
  68. }
  69. }
  70. break;
  71. case BA_ESC_RETURN_BOUNDS:
  72. {
  73. //
  74. // The share core has completed its processing of the bounds
  75. // which we passed on the BA_ESC_GET_BOUNDS escape. We have to
  76. // reset the spoiling rectangles and add any bounds which the
  77. // share core failed to process into our current bounds.
  78. //
  79. //
  80. // To reset the spoiling bounds we just have to reset the
  81. // number of bounds.
  82. //
  83. g_baNumSpoilingRects = 0;
  84. //
  85. // Now add the share core's bounds into our current bounds
  86. //
  87. pBoundsInfo = (LPBA_BOUNDS_INFO)pRequest;
  88. TRACE_OUT(( "Received %d rects from share core",
  89. pBoundsInfo->numRects));
  90. for (i = 0 ; i < pBoundsInfo->numRects ; i++)
  91. {
  92. RECTL_TO_RECT(&pBoundsInfo->rects[i], &rect);
  93. TRACE_OUT(( "Rect %d, {%d, %d, %d, %d}",
  94. i, rect.left, rect.top, rect.right, rect.bottom));
  95. BA_AddScreenData(&rect);
  96. }
  97. }
  98. break;
  99. default:
  100. {
  101. ERROR_OUT(( "Unrecognised BA escape"));
  102. rc = FALSE;
  103. }
  104. break;
  105. }
  106. DC_EXIT_POINT:
  107. DebugExitBOOL(BA_DDProcessRequest, rc);
  108. return(rc);
  109. }
  110. //
  111. // BA_DDInit - see ba.h for description.
  112. //
  113. void BA_DDInit(void)
  114. {
  115. DebugEntry(BA_DDInit);
  116. BA_ResetBounds();
  117. DebugExitVOID(BA_DDInit);
  118. }
  119. //
  120. // This gets a current version of our bound rect list, and clears it
  121. // afterwards if requested.
  122. //
  123. void BA_CopyBounds
  124. (
  125. LPRECT pRects,
  126. LPUINT pNumRects,
  127. BOOL fReset
  128. )
  129. {
  130. UINT i;
  131. #ifdef DEBUG
  132. UINT cRects = 0;
  133. #endif
  134. DebugEntry(BA_CopyBounds);
  135. if (*pNumRects = g_baRectsUsed)
  136. {
  137. //
  138. // Return the bounds that have been accumulated.
  139. //
  140. TRACE_OUT(( "num rects : %d", g_baRectsUsed));
  141. //
  142. // We can return the bounds in any order - we don't care how we
  143. // order the SDA rectangles.
  144. //
  145. // Also note that we must compare BA_NUM_RECTS + 1 sets of
  146. // rectangles because that's the number actually used by the add
  147. // rectangle code and while it guarantees that it will only use
  148. // BA_NUM_RECTS rectangles, it does not guarantee that the last
  149. // element in the array is the merge rectangle.
  150. //
  151. for (i = 0; i <= BA_NUM_RECTS; i++)
  152. {
  153. if (g_baBounds[i].InUse)
  154. {
  155. TRACE_OUT(("Found rect: {%04d,%04d,%04d,%04d}",
  156. g_baBounds[i].Coord.left, g_baBounds[i].Coord.top,
  157. g_baBounds[i].Coord.right, g_baBounds[i].Coord.bottom));
  158. *pRects = g_baBounds[i].Coord;
  159. pRects++;
  160. #ifdef DEBUG
  161. cRects++;
  162. #endif
  163. }
  164. }
  165. //
  166. // Check for self-consistency
  167. //
  168. ASSERT(cRects == *pNumRects);
  169. if (fReset)
  170. BA_ResetBounds();
  171. }
  172. DebugExitVOID(BACopyBounds);
  173. }
  174. //
  175. //
  176. // BA_AddScreenData(..)
  177. //
  178. // Adds the specified rectangle to the current Screen Data Area.
  179. //
  180. // Called by the GDI interception code for orders that it cannot send as
  181. // orders.
  182. //
  183. // NOTE that the rectangle is INCLUSIVE coords
  184. //
  185. //
  186. void BA_AddScreenData(LPRECT pRect)
  187. {
  188. RECT preRects[BA_NUM_RECTS];
  189. RECT postRects[BA_NUM_RECTS];
  190. UINT numPreRects;
  191. UINT numPostRects;
  192. UINT i;
  193. DebugEntry(BA_AddScreenData);
  194. //
  195. // Check that the caller has passed a valid rectangle. If not, do a
  196. // trace alert, and then return immediately (as an invalid rectangle
  197. // shouldn't contribute to the accumulated bounds) - but report an OK
  198. // return code, so we keep running.
  199. //
  200. if ((pRect->right < pRect->left) ||
  201. (pRect->bottom < pRect->top) )
  202. {
  203. WARNING_OUT(( "Invalid Add Rect (%d,%d,%d,%d)",
  204. pRect->left,
  205. pRect->top,
  206. pRect->right,
  207. pRect->bottom ));
  208. DC_QUIT;
  209. }
  210. if ((g_oaFlow == OAFLOW_SLOW) && g_baSpoilByNewSDAEnabled)
  211. {
  212. //
  213. // We are spoiling existing orders by new SDA, so query the current
  214. // bounds.
  215. //
  216. BA_CopyBounds(preRects, &numPreRects, FALSE);
  217. }
  218. //
  219. // Add the rect to the bounds.
  220. //
  221. if (BAAddRect(pRect, 0))
  222. {
  223. if ((pRect->right > pRect->left) && (pRect->bottom > pRect->top))
  224. {
  225. LPBA_FAST_DATA lpbaFast;
  226. lpbaFast = BA_FST_START_WRITING;
  227. SHM_CheckPointer(lpbaFast);
  228. lpbaFast->totalSDA += COM_SizeOfRectInclusive(pRect);
  229. TRACE_OUT(("Added rect to bounds, giving %ld of SD", lpbaFast->totalSDA));
  230. //
  231. // This is where the Win95 product would make a call to
  232. // DCS_TriggerEarlyTimer
  233. //
  234. BA_FST_STOP_WRITING;
  235. }
  236. if ((g_oaFlow == OAFLOW_SLOW) && g_baSpoilByNewSDAEnabled)
  237. {
  238. //
  239. // Adding the new rectangle changed the existing bounds so
  240. // query the new bounds
  241. //
  242. BA_CopyBounds(postRects, &numPostRects, FALSE);
  243. //
  244. // Try to spoil existing orders using each of the rectangles
  245. // which have changed.
  246. //
  247. for (i = 0; i < numPostRects; i++)
  248. {
  249. if ( (i > numPreRects) ||
  250. (postRects[i].left != preRects[i].left) ||
  251. (postRects[i].right != preRects[i].right) ||
  252. (postRects[i].top != preRects[i].top) ||
  253. (postRects[i].bottom != preRects[i].bottom) )
  254. {
  255. OA_DDSpoilOrdersByRect(&postRects[i]);
  256. }
  257. }
  258. }
  259. }
  260. DC_EXIT_POINT:
  261. DebugExitVOID(BA_AddScreenData);
  262. }
  263. //
  264. //
  265. // BA_QuerySpoilingBounds() - see ba.h
  266. //
  267. //
  268. void BA_QuerySpoilingBounds(LPRECT pRects, LPUINT pNumRects)
  269. {
  270. DebugEntry(BA_QuerySpoilingBounds);
  271. //
  272. // Just have to return the number of spoiling rectangles, and the
  273. // rectangles themselves. No rectangles is perfectly valid.
  274. //
  275. TRACE_OUT(( "Num rects %d", g_baNumSpoilingRects));
  276. *pNumRects = g_baNumSpoilingRects;
  277. memcpy(pRects, g_baSpoilingRects, g_baNumSpoilingRects*sizeof(RECT));
  278. DebugExitVOID(BA_QuerySpoilingBounds);
  279. }
  280. void BA_ResetBounds(void)
  281. {
  282. UINT i;
  283. DebugEntry(BA_ResetBounds);
  284. //
  285. // Clear the bounds - reset the number we are using, mark all slots as
  286. // free, and clean the list.
  287. //
  288. for ( i = 0; i <= BA_NUM_RECTS; i++ )
  289. {
  290. g_baBounds[i].InUse = FALSE;
  291. g_baBounds[i].iNext = BA_INVALID_RECT_INDEX;
  292. }
  293. g_baFirstRect = BA_INVALID_RECT_INDEX;
  294. g_baLastRect = BA_INVALID_RECT_INDEX;
  295. g_baRectsUsed = 0;
  296. DebugExitVOID(BA_ResetBounds);
  297. }
  298. //
  299. // Name: BAOverlap
  300. //
  301. // Description: Detects overlap between two rectangles.
  302. //
  303. // - check for no overlap using loose test that lets through
  304. // adjacent/overlapping merges
  305. // - check for adjacent/overlapping merges
  306. // - check for no overlap (using strict test)
  307. // - use outcodes to check internal edge cases
  308. // - use outcodes to check external edge cases
  309. //
  310. // If at each stage the check detects that the two rectangles
  311. // meet the criteria, the function returns the appropriate
  312. // return or outcode combination.
  313. //
  314. // Note that all rectangle coordinates are inclusive, ie
  315. // a rectangle of 0,0,0,0 has an area of 1 pel.
  316. //
  317. // This function does not alter either of the rectangles.
  318. //
  319. // Params (IN): pRect1 - first rectangle
  320. // pRect2 - second rectangle
  321. //
  322. // Returns: One of the overlap return codes or outcode combinations
  323. // defined above.
  324. //
  325. //
  326. int BAOverlap(LPRECT pRect1, LPRECT pRect2 )
  327. {
  328. int ExternalEdges;
  329. int ExternalCount;
  330. int InternalEdges;
  331. int InternalCount;
  332. //
  333. // Check for no overlap.
  334. //
  335. // Note that this test is looser than strict no overlap, and will let
  336. // through rectangles that do not overlap, but just abutt by one pel -
  337. // so that we get a chance to detect adjacent merges.
  338. //
  339. // So (for example) for the following:
  340. //
  341. // - it detects no overlap when there is at least 1 pel between rects
  342. //
  343. // 10,10 52,10
  344. // +----------++----------+
  345. // | || |
  346. // | || |
  347. // | || |
  348. // | Rect 1 || Rect 2 |
  349. // | || |
  350. // | || |
  351. // | || |
  352. // +----------++----------+
  353. // 50,50 100,50
  354. //
  355. // - it allows rectangles through when they abutt and are mergable
  356. //
  357. // 10,10 51,10
  358. // +----------++----------+
  359. // | || |
  360. // | || |
  361. // | || |
  362. // | Rect 1 || Rect 2 |
  363. // | || |
  364. // | || |
  365. // | || |
  366. // +----------++----------+
  367. // 50,50 100,50
  368. //
  369. // - it allows rectangles through when they abutt, even where they are
  370. // not mergable
  371. //
  372. // 10,10
  373. // +----------+51,15
  374. // | |+----------+
  375. // | || |
  376. // | || |
  377. // | Rect 1 || |
  378. // | || Rect 2 |
  379. // | || |
  380. // | || |
  381. // +----------+| |
  382. // 50,50+----------+
  383. // 100,55
  384. //
  385. // - it allows rectangles through when they overlap in some way
  386. //
  387. // 40,0
  388. // +------------+
  389. // 10,10 | |
  390. // +-------+--+ |
  391. // | | | |
  392. // | | | Rect 2 |
  393. // | | | |
  394. // |Rect 1 | | |
  395. // | | | |
  396. // | +--+---------+
  397. // | | 90,40
  398. // +----------+
  399. // 50,50
  400. //
  401. //
  402. if (!((pRect1->left <= pRect2->right + 1) &&
  403. (pRect1->top <= pRect2->bottom + 1) &&
  404. (pRect1->right >= pRect2->left - 1) &&
  405. (pRect1->bottom >= pRect2->top - 1) ))
  406. {
  407. return(OL_NONE);
  408. }
  409. //
  410. // Check for adjoining/overlapping rectangles which can be merged.
  411. //
  412. // These tests detect (for example for the XMAX variant), where:
  413. //
  414. // - the rectangles abutt and can be merged
  415. //
  416. // 10,10 51,10
  417. // +----------++----------+
  418. // | || |
  419. // | || |
  420. // | || |
  421. // | Rect 1 || Rect 2 |
  422. // | || |
  423. // | || |
  424. // | || |
  425. // +----------++----------+
  426. // 50,50 100,50
  427. //
  428. // - the rectangles overlap and can be merged
  429. //
  430. // 10,10 40,10
  431. // +-------+--+------+
  432. // | | | |
  433. // | | | |
  434. // | | | |
  435. // |Rect 1 | |Rect 2|
  436. // | | | |
  437. // | | | |
  438. // | | | |
  439. // +-------+--+------+
  440. // 50,50 90,50
  441. //
  442. // - the rectangles abutt and cannot be merged - this case is detected
  443. // by the strict overlap case below
  444. //
  445. // 10,10
  446. // +----------+51,15
  447. // | |+----------+
  448. // | || |
  449. // | || |
  450. // | Rect 1 || |
  451. // | || Rect 2 |
  452. // | || |
  453. // | || |
  454. // +----------+| |
  455. // 50,50+----------+
  456. // 100,55
  457. //
  458. // - the rectangles overlap and cannot be merged - this case is
  459. // detected by the outcode tests below
  460. //
  461. // 40,0
  462. // +------------+
  463. // 10,10 | |
  464. // +-------+--+ |
  465. // | | | |
  466. // | | | Rect 2 |
  467. // | | | |
  468. // |Rect 1 | | |
  469. // | | | |
  470. // | +--+---------+
  471. // | | 90,40
  472. // +----------+
  473. // 50,50
  474. //
  475. // - rectangle 2 is enclosed in rectangle 1 and should not be merged -
  476. // this case is detected by the outcode tests below.
  477. //
  478. // 10,10 40,10
  479. // +-------+------+-----+
  480. // | | | |
  481. // | | | |
  482. // | | | |
  483. // |Rect 1 |Rect 2| |
  484. // | | | |
  485. // | | | |
  486. // | | | |
  487. // +-------+------+-----+
  488. // 60,50 90,50
  489. // Rect2 Rect1
  490. //
  491. //
  492. if ( (pRect1->left <= pRect2->right + 1) &&
  493. (pRect1->left > pRect2->left ) &&
  494. (pRect1->right > pRect2->right ) &&
  495. (pRect1->top == pRect2->top ) &&
  496. (pRect1->bottom == pRect2->bottom ) )
  497. {
  498. return(OL_MERGE_XMIN);
  499. }
  500. if ( (pRect1->top <= pRect2->bottom + 1) &&
  501. (pRect1->top > pRect2->top ) &&
  502. (pRect1->bottom > pRect2->bottom ) &&
  503. (pRect1->left == pRect2->left ) &&
  504. (pRect1->right == pRect2->right ) )
  505. {
  506. return(OL_MERGE_YMIN);
  507. }
  508. if ( (pRect1->right >= pRect2->left - 1) &&
  509. (pRect1->right < pRect2->right ) &&
  510. (pRect1->left < pRect2->left ) &&
  511. (pRect1->top == pRect2->top ) &&
  512. (pRect1->bottom == pRect2->bottom ) )
  513. {
  514. return(OL_MERGE_XMAX);
  515. }
  516. if ( (pRect1->bottom >= pRect2->top - 1) &&
  517. (pRect1->bottom < pRect2->bottom ) &&
  518. (pRect1->top < pRect2->top ) &&
  519. (pRect1->left == pRect2->left ) &&
  520. (pRect1->right == pRect2->right ) )
  521. {
  522. return(OL_MERGE_YMAX);
  523. }
  524. //
  525. // Check for no overlap.
  526. // Note that this test is a stricter version than the earlier one, so
  527. // that we now only continue testing rectangles that do genuinely
  528. // overlap.
  529. //
  530. if (!((pRect1->left <= pRect2->right) &&
  531. (pRect1->top <= pRect2->bottom) &&
  532. (pRect1->right >= pRect2->left) &&
  533. (pRect1->bottom >= pRect2->top) ))
  534. {
  535. return(OL_NONE);
  536. }
  537. //
  538. // Use outcodes for Internal edge cases, as follows:
  539. //
  540. // EE_XMIN - rect1 xmin is enclosed within rect2
  541. // EE_YMIN - rect1 ymin is enclosed within rect2
  542. // EE_XMAX - rect1 xmax is enclosed within rect2
  543. // EE_YMAX - rect1 ymax is enclosed within rect2
  544. //
  545. // If 3 or more bits are set then rect1 is enclosed either partially or
  546. // completely within rect2 as follows (see individual switch cases for
  547. // diagrams).
  548. //
  549. // OL_ENCLOSED = EE_XMIN | EE_YMIN | EE_XMAX | EE_YMAX
  550. // OL_PART_ENCLOSED_XMIN = EE_XMIN | EE_YMIN | EE_YMAX
  551. // OL_PART_ENCLOSED_YMIN = EE_XMIN | EE_YMIN | EE_XMAX
  552. // OL_PART_ENCLOSED_XMAX = EE_YMIN | EE_XMAX | EE_YMAX
  553. // OL_PART_ENCLOSED_YMAX = EE_XMIN | EE_XMAX | EE_YMAX
  554. //
  555. // In practice, if 3 or more bits are set, the negative of the outcode
  556. // value is retruned to ensure that it is distinct from the external
  557. // edge outcode returns (see below).
  558. //
  559. //
  560. InternalCount = 0;
  561. InternalEdges = 0;
  562. if ( pRect1->left >= pRect2->left && pRect1->left <= pRect2->right)
  563. {
  564. InternalEdges |= EE_XMIN;
  565. InternalCount ++;
  566. }
  567. if ( pRect1->top >= pRect2->top && pRect1->top <= pRect2->bottom)
  568. {
  569. InternalEdges |= EE_YMIN;
  570. InternalCount ++;
  571. }
  572. if ( pRect1->right >= pRect2->left && pRect1->right <= pRect2->right)
  573. {
  574. InternalEdges |= EE_XMAX;
  575. InternalCount ++;
  576. }
  577. if ( pRect1->bottom >= pRect2->top && pRect1->bottom <= pRect2->bottom)
  578. {
  579. InternalEdges |= EE_YMAX;
  580. InternalCount ++;
  581. }
  582. if ( InternalCount >= 3)
  583. {
  584. return(-InternalEdges);
  585. }
  586. //
  587. // Use outcodes for External edge cases as follows.
  588. //
  589. // EE_XMIN - rect1 xmin is left of rect2 xmin
  590. // EE_YMIN - rect1 ymin is above rect2 ymin
  591. // EE_XMAX - rect1 xmax is right of rect2 xmax
  592. // EE_YMAX - rect1 ymax is below rect2 ymax
  593. //
  594. // These are the classic "line" outcodes.
  595. //
  596. // If 2 or more bits are set then rect1 overlaps rect2 as follows (see
  597. // individual switch cases for diagrams).
  598. //
  599. // OL_ENCLOSES = EE_XMIN | EE_YMIN | EE_XMAX | EE_YMAX
  600. // OL_PART_ENCLOSES_XMIN = EE_YMIN | EE_XMAX | EE_YMAX
  601. // OL_PART_ENCLOSES_XMAX = EE_XMIN | EE_YMIN | EE_YMAX
  602. // OL_PART_ENCLOSES_YMIN = EE_XMIN | EE_XMAX | EE_YMAX
  603. // OL_PART_ENCLOSES_YMAX = EE_XMIN | EE_YMIN | EE_XMAX
  604. // OL_SPLIT_X = EE_YMIN | EE_YMAX
  605. // OL_SPLIT_Y = EE_XMIN | EE_XMAX
  606. // OL_SPLIT_XMIN_YMIN = EE_XMAX | EE_YMAX
  607. // OL_SPLIT_XMAX_YMIN = EE_XMIN | EE_YMAX
  608. // OL_SPLIT_XMIN_YMAX = EE_YMIN | EE_XMAX
  609. // OL_SPLIT_XMAX_YMAX = EE_XMIN | EE_YMIN
  610. //
  611. // The accumulated outcode value is returned.
  612. //
  613. //
  614. ExternalEdges = 0;
  615. ExternalCount = 0;
  616. if ( pRect1->left <= pRect2->left )
  617. {
  618. ExternalEdges |= EE_XMIN;
  619. ExternalCount ++;
  620. }
  621. if ( pRect1->top <= pRect2->top )
  622. {
  623. ExternalEdges |= EE_YMIN;
  624. ExternalCount ++;
  625. }
  626. if ( pRect1->right >= pRect2->right )
  627. {
  628. ExternalEdges |= EE_XMAX;
  629. ExternalCount ++;
  630. }
  631. if ( pRect1->bottom >= pRect2->bottom )
  632. {
  633. ExternalEdges |= EE_YMAX;
  634. ExternalCount ++;
  635. }
  636. if (ExternalCount >= 2)
  637. {
  638. return(ExternalEdges);
  639. }
  640. //
  641. // If get here then we failed to detect a valid case.
  642. //
  643. WARNING_OUT(( "Unrecognised Overlap: (%d,%d,%d,%d),(%d,%d,%d,%d)",
  644. pRect1->left, pRect1->top, pRect1->right, pRect1->bottom,
  645. pRect2->left, pRect2->top, pRect2->right, pRect2->bottom ));
  646. return(OL_NONE);
  647. }
  648. //
  649. // Name: BAAddRectList
  650. //
  651. // Description: Adds a rectangle to the list of accumulated rectangles.
  652. //
  653. // - find a free slot in the array
  654. // - add slot record to list
  655. // - fill slot record with rect and mark as in use.
  656. //
  657. // Params (IN): pRect - rectangle to add
  658. //
  659. // Returns:
  660. //
  661. //
  662. void BAAddRectList(LPRECT pRect)
  663. {
  664. UINT i;
  665. BOOL fFoundFreeSlot;
  666. DebugEntry(BAAddRectList);
  667. //
  668. // Find a free slot in the array. Note that the loop searches to
  669. // BA_NUM_RECTS+1, because:
  670. //
  671. // - the array is defined as having one more slot than BA_NUM_RECTS
  672. //
  673. // - we may need to add a rect in that slot when BA_NUM_RECTS are
  674. // in use prior to a forced merge.
  675. //
  676. fFoundFreeSlot = FALSE;
  677. for ( i = 0; i <= BA_NUM_RECTS; i++ )
  678. {
  679. if (!g_baBounds[i].InUse)
  680. {
  681. fFoundFreeSlot = TRUE;
  682. break;
  683. }
  684. }
  685. if (!fFoundFreeSlot)
  686. {
  687. WARNING_OUT(( "No space in array for rect (%d,%d,%d,%d)",
  688. pRect->left,
  689. pRect->top,
  690. pRect->right,
  691. pRect->bottom));
  692. for ( i = 0; i <= BA_NUM_RECTS; i++ )
  693. {
  694. WARNING_OUT((
  695. "Entry %i:Next(%lx),(%d,%d,%d,%d),Index(%d),InUse(%d)",
  696. g_baBounds[i].iNext,
  697. g_baBounds[i].Coord.left,
  698. g_baBounds[i].Coord.top,
  699. g_baBounds[i].Coord.right,
  700. g_baBounds[i].Coord.bottom,
  701. i,
  702. g_baBounds[i].InUse));
  703. }
  704. DC_QUIT;
  705. }
  706. //
  707. // If first rect, then set up list.
  708. // If not, add to tail of list.
  709. //
  710. if (g_baRectsUsed == 0)
  711. {
  712. g_baFirstRect = i;
  713. g_baLastRect = i;
  714. }
  715. else
  716. {
  717. g_baBounds[g_baLastRect].iNext = i;
  718. g_baLastRect = i;
  719. }
  720. g_baBounds[i].iNext = BA_INVALID_RECT_INDEX;
  721. //
  722. // Fill in slot and mark as in use.
  723. //
  724. g_baBounds[i].InUse = TRUE;
  725. g_baBounds[i].Coord = *pRect;
  726. //
  727. // Increment number of rectangles.
  728. //
  729. TRACE_OUT(( "Add Rect : ix - %d, (%d,%d,%d,%d)", i,
  730. pRect->left,pRect->top,pRect->right,pRect->bottom));
  731. g_baRectsUsed++;
  732. DC_EXIT_POINT:
  733. DebugExitVOID(BAAddRectList);
  734. }
  735. //
  736. // Name: BA_RemoveRectList
  737. //
  738. // Description: Removes a rectangle from the list of accumulated
  739. // rectangles.
  740. //
  741. // - find the rectangle in the list
  742. // - unlink it from the list and mark the slot as free
  743. //
  744. // Params (IN): pRect - rectangle to remove
  745. //
  746. // Returns:
  747. //
  748. //
  749. void BA_RemoveRectList(LPRECT pRect)
  750. {
  751. UINT i;
  752. UINT j;
  753. DebugEntry(BA_RemoveRectList);
  754. //
  755. // If rectangle to remove is first...
  756. // Remove it by adjusting first pointer and mark as free.
  757. // Note that the check for tail adjustment has to be done before we
  758. // change first.
  759. //
  760. if ( g_baBounds[g_baFirstRect].Coord.left == pRect->left &&
  761. g_baBounds[g_baFirstRect].Coord.top == pRect->top &&
  762. g_baBounds[g_baFirstRect].Coord.right == pRect->right &&
  763. g_baBounds[g_baFirstRect].Coord.bottom == pRect->bottom )
  764. {
  765. TRACE_OUT(( "Remove first"));
  766. if (g_baFirstRect == g_baLastRect)
  767. {
  768. g_baLastRect = BA_INVALID_RECT_INDEX;
  769. }
  770. g_baBounds[g_baFirstRect].InUse = FALSE;
  771. g_baFirstRect = g_baBounds[g_baFirstRect].iNext;
  772. }
  773. //
  774. // If rectangle to remove is not first...
  775. // Find it in list, remove it by adjusting previous pointer and mark it
  776. // as free.
  777. // Note that the check for tail adjustment has to be done before we
  778. // change the previous pointer.
  779. //
  780. else
  781. {
  782. TRACE_OUT(( "Remove not first"));
  783. for ( j = g_baFirstRect;
  784. g_baBounds[j].iNext != BA_INVALID_RECT_INDEX;
  785. j = g_baBounds[j].iNext )
  786. {
  787. if ( (g_baBounds[g_baBounds[j].iNext].Coord.left == pRect->left) &&
  788. (g_baBounds[g_baBounds[j].iNext].Coord.top == pRect->top) &&
  789. (g_baBounds[g_baBounds[j].iNext].Coord.right == pRect->right) &&
  790. (g_baBounds[g_baBounds[j].iNext].Coord.bottom == pRect->bottom) )
  791. {
  792. break;
  793. }
  794. }
  795. if (j == BA_INVALID_RECT_INDEX)
  796. {
  797. WARNING_OUT(( "Couldn't remove rect (%d,%d,%d,%d)",
  798. pRect->left,
  799. pRect->top,
  800. pRect->right,
  801. pRect->bottom ));
  802. for ( i = 0; i <= BA_NUM_RECTS; i++ )
  803. {
  804. WARNING_OUT((
  805. "Entry %i:Next(%lx),(%d,%d,%d,%d),Index(%d),InUse(%d)",
  806. g_baBounds[i].iNext,
  807. g_baBounds[i].Coord.left,
  808. g_baBounds[i].Coord.top,
  809. g_baBounds[i].Coord.right,
  810. g_baBounds[i].Coord.bottom,
  811. i,
  812. g_baBounds[i].InUse));
  813. }
  814. return;
  815. }
  816. if (g_baBounds[j].iNext == g_baLastRect )
  817. {
  818. g_baLastRect = j;
  819. }
  820. g_baBounds[g_baBounds[j].iNext].InUse = FALSE;
  821. g_baBounds[j].iNext = g_baBounds[g_baBounds[j].iNext].iNext;
  822. }
  823. //
  824. // One less rect...
  825. //
  826. g_baRectsUsed--;
  827. DebugExitVOID(BA_RemoveRectList);
  828. }
  829. //
  830. // Name: BAAddRect
  831. //
  832. // Description: Accumulates rectangles.
  833. //
  834. // This is a complex routine, with the essential algorithm
  835. // as follows.
  836. //
  837. // - Start with the supplied rectangle as the candidate
  838. // rectangle.
  839. //
  840. // - Compare the candidate against each of the existing
  841. // accumulated rectangles.
  842. //
  843. // - If some form of overlap is detected between the
  844. // candidate and an existing rectangle, this may result in
  845. // one of the following (see the cases of the switch for
  846. // details):
  847. //
  848. // - adjust the candidate or the existing rectangle or both
  849. // - merge the candidate into the existing rectangle
  850. // - discard the candidate as it is enclosed by an existing
  851. // rectangle.
  852. //
  853. // - If the merge or adjustment results in a changed
  854. // candidate, restart the comparisons from the beginning of
  855. // the list with the changed candidate.
  856. //
  857. // - If the adjustment results in a split (giving two
  858. // candidate rectangles), invoke this routine recursively
  859. // with one of the two candidates as its candidate.
  860. //
  861. // - If no overlap is detected against the existing rectangles,
  862. // add the candidate to the list of accumulated rectangles.
  863. //
  864. // - If the add results in more than BA_NUM_RECTS
  865. // accumulated rectangles, do a forced merge of two of the
  866. // accumulate rectangles (which include the newly added
  867. // candidate) - choosing the two rectangles where the merged
  868. // rectangle results in the smallest increase in area over
  869. // the two non-merged rectangles.
  870. //
  871. // - After a forced merge, restart the comparisons from the
  872. // beginning of the list with the newly merged rectangle as
  873. // the candidate.
  874. //
  875. // For a particular call, this process will continue until
  876. // the candidate (whether the supplied rectangle, an adjusted
  877. // version of that rectangle, or a merged rectangle):
  878. //
  879. // - does not find an overlap among the rectangles in the list
  880. // and does not cause a forced merge
  881. // - is discarded becuase it is enclosed within one of the
  882. // rectangles in the list.
  883. //
  884. // Note that all rectangle coordinates are inclusive, ie
  885. // a rectangle of 0,0,0,0 has an area of 1 pel.
  886. //
  887. // Params (IN): pCand - new candidate rectangle
  888. // level - recursion level
  889. //
  890. // Returns: TRUE if rectandle was spoilt due to a complete overlap.
  891. //
  892. //
  893. BOOL BAAddRect
  894. (
  895. LPRECT pCand,
  896. int level
  897. )
  898. {
  899. int bestMergeIncrease;
  900. int mergeIncrease;
  901. UINT iBestMerge1;
  902. UINT iBestMerge2;
  903. UINT iExist;
  904. UINT iTmp;
  905. BOOL fRectToAdd;
  906. BOOL fRectMerged;
  907. BOOL fResetRects;
  908. RECT rectNew;
  909. UINT iLastMerge;
  910. int OverlapType;
  911. BOOL rc = TRUE;
  912. DebugEntry(BAAddRect);
  913. //
  914. // Increase the level count in case we recurse.
  915. //
  916. level++;
  917. //
  918. // Start off by assuming the candidate rectangle will be added to the
  919. // accumulated list of rectangles, and that no merges will occur.
  920. //
  921. fRectToAdd = TRUE;
  922. fRectMerged = FALSE;
  923. //
  924. // Loop until no merges occur.
  925. //
  926. do
  927. {
  928. TRACE_OUT(( "Candidate rect: (%d,%d,%d,%d)",
  929. pCand->left,pCand->top,pCand->right,pCand->bottom));
  930. //
  931. // Compare the current candidate rectangle against the rectangles
  932. // in the current accumulated list.
  933. //
  934. iExist = g_baFirstRect;
  935. while (iExist != BA_INVALID_RECT_INDEX)
  936. {
  937. //
  938. // Assume that the comparisons will run through the whole list.
  939. //
  940. fResetRects = FALSE;
  941. //
  942. // If the candidate and the existing rectangle are the same
  943. // then ignore. This occurs when an existing rectangle is
  944. // replaced by a candidate and the comparisons are restarted
  945. // from the front of the list - whereupon at some point the
  946. // candidate will be compared with itself.
  947. //
  948. if ( &g_baBounds[iExist].Coord == pCand )
  949. {
  950. TRACE_OUT(( "OL_SAME - %d", iExist));
  951. iExist = g_baBounds[iExist].iNext;
  952. continue;
  953. }
  954. //
  955. // Switch on the overlap type (see Overlap routine).
  956. //
  957. OverlapType = BAOverlap(&(g_baBounds[iExist].Coord), pCand);
  958. switch (OverlapType)
  959. {
  960. case OL_NONE:
  961. //
  962. // No overlap.
  963. //
  964. TRACE_OUT(( "OL_NONE - %d", iExist));
  965. break;
  966. case OL_MERGE_XMIN:
  967. //
  968. // - either the candidate abutts the existing rectangle
  969. // on the left
  970. //
  971. // 10,10 51,10
  972. // +----------++----------+
  973. // | || |
  974. // | || |
  975. // | || |
  976. // | Cand || Exist |
  977. // | || |
  978. // | || |
  979. // | || |
  980. // +----------++----------+
  981. // 50,50 100,50
  982. //
  983. // - or the candidate overlaps the existing on the left
  984. // and can be merged
  985. //
  986. // 10,10 40,10
  987. // +-------+--+------+
  988. // | | | |
  989. // | | | |
  990. // | | | |
  991. // | Cand | |Exist |
  992. // | | | |
  993. // | | | |
  994. // | | | |
  995. // +-------+--+------+
  996. // 50,50 90,50
  997. //
  998. // If the candidate is the original, merge the
  999. // candidate into the existing, and make the existing
  1000. // the new candidate.
  1001. //
  1002. // If this is a merge of two existing rectangles (ie
  1003. // the candidate is the result of a merge), merge the
  1004. // overlapping existing into the candidate (the last
  1005. // merged) and remove the existing.
  1006. //
  1007. // For both, start the comparisons again with the new
  1008. // candidate.
  1009. //
  1010. TRACE_OUT(( "OL_MERGE_XMIN - %d", iExist));
  1011. if ( fRectToAdd )
  1012. {
  1013. g_baBounds[iExist].Coord.left = pCand->left;
  1014. pCand = &(g_baBounds[iExist].Coord);
  1015. fRectToAdd = FALSE;
  1016. iLastMerge = iExist;
  1017. }
  1018. else
  1019. {
  1020. pCand->right = g_baBounds[iExist].Coord.right;
  1021. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1022. }
  1023. fResetRects = TRUE;
  1024. break;
  1025. case OL_MERGE_XMAX:
  1026. //
  1027. // - either the candidate abutts the existing rectangle
  1028. // on the right
  1029. //
  1030. // 10,10 51,10
  1031. // +----------++----------+
  1032. // | || |
  1033. // | || |
  1034. // | || |
  1035. // | Exist || Cand |
  1036. // | || |
  1037. // | || |
  1038. // | || |
  1039. // +----------++----------+
  1040. // 50,50 100,50
  1041. //
  1042. // - or the candidate overlaps the existing on the right
  1043. // and can be merged
  1044. //
  1045. // 10,10 40,10
  1046. // +-------+--+------+
  1047. // | | | |
  1048. // | | | |
  1049. // | | | |
  1050. // | Exist | | Cand |
  1051. // | | | |
  1052. // | | | |
  1053. // | | | |
  1054. // +-------+--+------+
  1055. // 50,50 90,50
  1056. //
  1057. // If the candidate is the original, merge the
  1058. // candidate into the existing, and make the existing
  1059. // the new candidate.
  1060. //
  1061. // If this is a merge of two existing rectangles (ie
  1062. // the candidate is the result of a merge), merge the
  1063. // overlapping existing into the candidate (the last
  1064. // merged) and remove the existing.
  1065. //
  1066. // For both, start the comparisons again with the new
  1067. // candidate.
  1068. //
  1069. TRACE_OUT(( "OL_MERGE_XMAX - %d", iExist));
  1070. if ( fRectToAdd )
  1071. {
  1072. g_baBounds[iExist].Coord.right = pCand->right;
  1073. pCand = &(g_baBounds[iExist].Coord);
  1074. fRectToAdd = FALSE;
  1075. iLastMerge = iExist;
  1076. }
  1077. else
  1078. {
  1079. pCand->left = g_baBounds[iExist].Coord.left;
  1080. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1081. }
  1082. fResetRects = TRUE;
  1083. break;
  1084. case OL_MERGE_YMIN:
  1085. //
  1086. // - either the candidate abutts the existing rectangle
  1087. // on the top
  1088. //
  1089. // 10,10
  1090. // +---------+
  1091. // | |
  1092. // | |
  1093. // | |
  1094. // | Cand |
  1095. // | |
  1096. // | |
  1097. // | |
  1098. // +---------+50,50
  1099. // 10,51+---------+
  1100. // | |
  1101. // | |
  1102. // | |
  1103. // | Exist |
  1104. // | |
  1105. // | |
  1106. // | |
  1107. // +---------+50,100
  1108. //
  1109. // - or the candidate overlaps the existing on the top
  1110. // and can be merged
  1111. //
  1112. // 10,10
  1113. // +---------+
  1114. // | |
  1115. // | |
  1116. // | |
  1117. // | Cand |
  1118. // | |
  1119. // | |
  1120. // Exist 10,40+---------+
  1121. // | |
  1122. // | |
  1123. // | |
  1124. // +---------+50,60 Cand
  1125. // | |
  1126. // | Exist |
  1127. // | |
  1128. // | |
  1129. // | |
  1130. // +---------+50,100
  1131. //
  1132. // If the candidate is the original, merge the
  1133. // candidate into the existing, and make the existing
  1134. // the new candidate.
  1135. //
  1136. // If this is a merge of two existing rectangles (ie
  1137. // the candidate is the result of a merge), merge the
  1138. // overlapping existing into the candidate (the last
  1139. // merged) and remove the existing.
  1140. //
  1141. // For both, start the comparisons again with the new
  1142. // candidate.
  1143. //
  1144. TRACE_OUT(( "OL_MERGE_YMIN - %d", iExist));
  1145. if ( fRectToAdd )
  1146. {
  1147. g_baBounds[iExist].Coord.top = pCand->top;
  1148. pCand = &(g_baBounds[iExist].Coord);
  1149. fRectToAdd = FALSE;
  1150. iLastMerge = iExist;
  1151. }
  1152. else
  1153. {
  1154. pCand->bottom = g_baBounds[iExist].Coord.bottom;
  1155. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1156. }
  1157. fResetRects = TRUE;
  1158. break;
  1159. case OL_MERGE_YMAX:
  1160. //
  1161. // - either the candidate abutts the existing rectangle
  1162. // from below
  1163. //
  1164. // 10,10
  1165. // +---------+
  1166. // | |
  1167. // | |
  1168. // | |
  1169. // | Exist |
  1170. // | |
  1171. // | |
  1172. // | |
  1173. // +---------+50,50
  1174. // 10,51+---------+
  1175. // | |
  1176. // | |
  1177. // | |
  1178. // | Cand |
  1179. // | |
  1180. // | |
  1181. // | |
  1182. // +---------+50,100
  1183. //
  1184. // - or the candidate overlaps the existing from below
  1185. // and can be merged
  1186. //
  1187. // 10,10
  1188. // +---------+
  1189. // | |
  1190. // | |
  1191. // | |
  1192. // | Exist |
  1193. // | |
  1194. // | |
  1195. // Cand 10,40+---------+
  1196. // | |
  1197. // | |
  1198. // | |
  1199. // +---------+50,60 Exist
  1200. // | |
  1201. // | Cand |
  1202. // | |
  1203. // | |
  1204. // | |
  1205. // +---------+50,100
  1206. //
  1207. // If the candidate is the original, merge the
  1208. // candidate into the existing, and make the existing
  1209. // the new candidate.
  1210. //
  1211. // If this is a merge of two existing rectangles (ie
  1212. // the candidate is the result of a merge), merge the
  1213. // overlapping existing into the candidate (the last
  1214. // merged) and remove the existing.
  1215. //
  1216. // For both, start the comparisons again with the new
  1217. // candidate.
  1218. //
  1219. TRACE_OUT(( "OL_MERGE_YMAX - %d", iExist));
  1220. if ( fRectToAdd )
  1221. {
  1222. g_baBounds[iExist].Coord.bottom = pCand->bottom;
  1223. pCand = &(g_baBounds[iExist].Coord);
  1224. fRectToAdd = FALSE;
  1225. iLastMerge = iExist;
  1226. }
  1227. else
  1228. {
  1229. pCand->top = g_baBounds[iExist].Coord.top;
  1230. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1231. }
  1232. fResetRects = TRUE;
  1233. break;
  1234. case OL_ENCLOSED:
  1235. //
  1236. // The existing is enclosed by the candidate.
  1237. //
  1238. // 100,100
  1239. // +----------------------+
  1240. // | Cand |
  1241. // | |
  1242. // | 130,130 |
  1243. // | +------------+ |
  1244. // | | | |
  1245. // | | | |
  1246. // | | Exist | |
  1247. // | | | |
  1248. // | +------------+ |
  1249. // | 170,170 |
  1250. // | |
  1251. // +----------------------+
  1252. // 200,200
  1253. //
  1254. // If the candidate is the original, replace the
  1255. // existing by the candidate, and make the new existing
  1256. // the new candidate.
  1257. //
  1258. // If the candidate is an existing rectangle, remove
  1259. // the other existing rectangle.
  1260. //
  1261. // For both, start the comparisons again with the new
  1262. // candidate.
  1263. //
  1264. TRACE_OUT(( "OL_ENCLOSED - %d", iExist));
  1265. if ( fRectToAdd )
  1266. {
  1267. g_baBounds[iExist].Coord = *pCand;
  1268. pCand = &(g_baBounds[iExist].Coord);
  1269. fRectToAdd = FALSE;
  1270. iLastMerge = iExist;
  1271. }
  1272. else
  1273. {
  1274. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1275. }
  1276. fResetRects = TRUE;
  1277. break;
  1278. case OL_PART_ENCLOSED_XMIN:
  1279. //
  1280. // The existing is partially enclosed by the candidate
  1281. // - but not on the right.
  1282. //
  1283. // 100,100
  1284. // +----------------------+
  1285. // | Cand |
  1286. // | |
  1287. // | 130,130 |
  1288. // | +-----------------+---+
  1289. // | | | |
  1290. // | | | |
  1291. // | | Exist | |
  1292. // | | | |
  1293. // | +-----------------+---+
  1294. // | | 220,170
  1295. // | |
  1296. // +----------------------+
  1297. // 200,200
  1298. //
  1299. // Adjust the existing rectangle to be the non-
  1300. // overlapped portion.
  1301. //
  1302. // 100,100
  1303. // +----------------------+
  1304. // | |
  1305. // | |201,130
  1306. // | |+--+
  1307. // | ||E |
  1308. // | ||x |
  1309. // | Cand ||i |
  1310. // | ||s |
  1311. // | ||t |
  1312. // | || |
  1313. // | |+--+
  1314. // | | 220,170
  1315. // +----------------------+
  1316. // 200,200
  1317. //
  1318. // Note that this does not restart the comparisons.
  1319. //
  1320. TRACE_OUT(( "OL_PART_ENCLOSED_XMIN - %d", iExist));
  1321. g_baBounds[iExist].Coord.left = pCand->right + 1;
  1322. break;
  1323. case OL_PART_ENCLOSED_XMAX:
  1324. //
  1325. // The existing is partially enclosed by the candidate
  1326. // - but not on the left.
  1327. //
  1328. // 100,100
  1329. // +----------------------+
  1330. // | Cand |
  1331. // 70,130 | |
  1332. // +-----+---------------+ |
  1333. // | | | |
  1334. // | | | |
  1335. // | | Exist | |
  1336. // | | | |
  1337. // +-----+---------------+ |
  1338. // | 170,170 |
  1339. // | |
  1340. // +----------------------+
  1341. // 200,200
  1342. //
  1343. // Adjust the existing rectangle to be the non-
  1344. // overlapped portion.
  1345. //
  1346. // 100,100
  1347. // +----------------------+
  1348. // 70,130 | |
  1349. // +----+| |
  1350. // | E || |
  1351. // | x || |
  1352. // | i || Cand |
  1353. // | s || |
  1354. // | t || |
  1355. // | || |
  1356. // +----+| |
  1357. // 99,170| |
  1358. // | |
  1359. // +----------------------+
  1360. // 200,200
  1361. //
  1362. // Note that this does not restart the comparisons.
  1363. //
  1364. TRACE_OUT(( "OL_PART_ENCLOSED_XMAX - %d", iExist));
  1365. g_baBounds[iExist].Coord.right = pCand->left - 1;
  1366. break;
  1367. case OL_PART_ENCLOSED_YMIN:
  1368. //
  1369. // The existing is partially enclosed by the candidate
  1370. // - but not on the bottom.
  1371. //
  1372. // 100,100
  1373. // +----------------------+
  1374. // | Cand |
  1375. // | 130,130 |
  1376. // | +--------+ |
  1377. // | | | |
  1378. // | | Exist | |
  1379. // | | | |
  1380. // | | | |
  1381. // | | | |
  1382. // | | | |
  1383. // | | | |
  1384. // +-----+--------+-------+
  1385. // | | 200,200
  1386. // | |
  1387. // | |
  1388. // +--------+170,230
  1389. //
  1390. // Adjust the existing rectangle to be the non-
  1391. // overlapped portion.
  1392. //
  1393. //
  1394. // 100,100
  1395. // +----------------------+
  1396. // | |
  1397. // | |
  1398. // | |
  1399. // | |
  1400. // | |
  1401. // | Cand |
  1402. // | |
  1403. // | |
  1404. // | |
  1405. // | |
  1406. // +----------------------+
  1407. // 130,201+---------+ 200,200
  1408. // | |
  1409. // | Exist |
  1410. // | |
  1411. // +---------+170,230
  1412. //
  1413. // Note that this does not restart the comparisons.
  1414. //
  1415. TRACE_OUT(( "OL_PART_ENCLOSED_YMIN - %d", iExist));
  1416. g_baBounds[iExist].Coord.top = pCand->bottom + 1;
  1417. break;
  1418. case OL_PART_ENCLOSED_YMAX:
  1419. //
  1420. // The existing is partially enclosed by the candidate
  1421. // - but not on the top.
  1422. //
  1423. // 70,130
  1424. // +---------+
  1425. // | |
  1426. // | |
  1427. // 100,100 | |
  1428. // +-----+---------+------+
  1429. // | | | |
  1430. // | | | |
  1431. // | | | |
  1432. // | | | |
  1433. // | | Exist | |
  1434. // | | | |
  1435. // | | | |
  1436. // | +---------+ |
  1437. // | 170,170 |
  1438. // | |
  1439. // | Cand |
  1440. // +----------------------+
  1441. // 200,200
  1442. //
  1443. // Adjust the existing rectangle to be the non-
  1444. // overlapped portion.
  1445. //
  1446. // 70,130
  1447. // +---------+
  1448. // | |
  1449. // | Exist |
  1450. // | |
  1451. // 100,100 +---------+170,99
  1452. // +----------------------+
  1453. // | |
  1454. // | |
  1455. // | |
  1456. // | |
  1457. // | |
  1458. // | Cand |
  1459. // | |
  1460. // | |
  1461. // | |
  1462. // | |
  1463. // +----------------------+
  1464. // 200,200
  1465. //
  1466. // Note that this does not restart the comparisons.
  1467. //
  1468. TRACE_OUT(( "OL_PART_ENCLOSED_YMAX - %d", iExist));
  1469. g_baBounds[iExist].Coord.bottom = pCand->top - 1;
  1470. break;
  1471. case OL_ENCLOSES:
  1472. //
  1473. // The existing encloses the candidate.
  1474. //
  1475. // 100,100
  1476. // +----------------------+
  1477. // | Exist |
  1478. // | |
  1479. // | 130,130 |
  1480. // | +------------+ |
  1481. // | | | |
  1482. // | | | |
  1483. // | | Cand | |
  1484. // | | | |
  1485. // | | | |
  1486. // | +------------+ |
  1487. // | 170,170 |
  1488. // | |
  1489. // +----------------------+
  1490. // 200,200
  1491. //
  1492. // Just discard the candidate by exiting.
  1493. //
  1494. //
  1495. TRACE_OUT(( "OL_ENCLOSES - %d", iExist));
  1496. //
  1497. // Return FALSE indicating that the rectangle is
  1498. // already catered for by the existing bounds
  1499. //
  1500. rc= FALSE;
  1501. DC_QUIT;
  1502. break;
  1503. case OL_PART_ENCLOSES_XMIN:
  1504. //
  1505. // The existing partially encloses the candidate - but
  1506. // not on the left.
  1507. //
  1508. // 100,100
  1509. // +----------------------+
  1510. // | Exist |
  1511. // 70,130 | |
  1512. // +-----+---------------+ |
  1513. // | | | |
  1514. // | | Cand | |
  1515. // | | | |
  1516. // +-----+---------------+ |
  1517. // | 170,170 |
  1518. // | |
  1519. // +----------------------+
  1520. // 200,200
  1521. //
  1522. // Adjust the candidate rectangle to be the non-
  1523. // overlapped portion.
  1524. //
  1525. // 100,100
  1526. // +----------------------+
  1527. // 70,130 | |
  1528. // +----+| |
  1529. // | || |
  1530. // | C || |
  1531. // | a || |
  1532. // | n || Exist |
  1533. // | d || |
  1534. // | || |
  1535. // +----+| |
  1536. // 99,170| |
  1537. // | |
  1538. // +----------------------+
  1539. // 200,200
  1540. //
  1541. // Because this affects the candidate, restart the
  1542. // comparisons to check for overlaps between the
  1543. // adjusted candidate and other existing rectangles.
  1544. //
  1545. //
  1546. TRACE_OUT(( "OL_PART_ENCLOSES_XMIN - %d", iExist));
  1547. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1548. fResetRects = TRUE;
  1549. break;
  1550. case OL_PART_ENCLOSES_XMAX:
  1551. //
  1552. // The existing partially encloses the candidate - but
  1553. // not on the right.
  1554. //
  1555. // 100,100
  1556. // +----------------------+
  1557. // | Exist |
  1558. // | |
  1559. // | 130,130 |
  1560. // | +-----------------+---+
  1561. // | | | |
  1562. // | | | |
  1563. // | | Cand | |
  1564. // | | | |
  1565. // | +-----------------+---+
  1566. // | | 220,170
  1567. // | |
  1568. // +----------------------+
  1569. // 200,200
  1570. //
  1571. // Adjust the candidate rectangle to be the non-
  1572. // overlapped portion.
  1573. //
  1574. // 100,100
  1575. // +----------------------+
  1576. // | |201,130
  1577. // | |+--+
  1578. // | || |
  1579. // | ||C |
  1580. // | Exist ||a |
  1581. // | ||n |
  1582. // | ||d |
  1583. // | || |
  1584. // | |+--+
  1585. // | | 220,170
  1586. // +----------------------+
  1587. // 200,200
  1588. //
  1589. // Because this affects the candidate, restart the
  1590. // comparisons to check for overlaps between the
  1591. // adjusted candidate and other existing rectangles.
  1592. //
  1593. //
  1594. TRACE_OUT(( "OL_PART_ENCLOSES_XMAX - %d", iExist));
  1595. pCand->left = g_baBounds[iExist].Coord.right + 1;
  1596. fResetRects = TRUE;
  1597. break;
  1598. case OL_PART_ENCLOSES_YMIN:
  1599. //
  1600. // The existing partially encloses the candidate - but
  1601. // not on the top.
  1602. //
  1603. // 70,130
  1604. // +---------+
  1605. // | |
  1606. // | |
  1607. // 100,100 | |
  1608. // +-----+---------+------+
  1609. // | | | |
  1610. // | | | |
  1611. // | | Cand | |
  1612. // | | | |
  1613. // | | | |
  1614. // | +---------+ |
  1615. // | 170,170 |
  1616. // | |
  1617. // | Exist |
  1618. // +----------------------+
  1619. // 200,200
  1620. //
  1621. // Adjust the candidate rectangle to be the non-
  1622. // overlapped portion.
  1623. //
  1624. //
  1625. // 70,130
  1626. // +---------+
  1627. // | |
  1628. // | Cand |
  1629. // | |
  1630. // 100,100 +---------+170,99
  1631. // +----------------------+
  1632. // | |
  1633. // | |
  1634. // | |
  1635. // | |
  1636. // | Exist |
  1637. // | |
  1638. // | |
  1639. // | |
  1640. // +----------------------+
  1641. // 200,200
  1642. //
  1643. // Because this affects the candidate, restart the
  1644. // comparisons to check for overlaps between the
  1645. // adjusted candidate and other existing rectangles.
  1646. //
  1647. //
  1648. TRACE_OUT(( "OL_PART_ENCLOSES_YMIN - %d", iExist));
  1649. pCand->bottom = g_baBounds[iExist].Coord.top - 1;
  1650. fResetRects = TRUE;
  1651. break;
  1652. case OL_PART_ENCLOSES_YMAX:
  1653. //
  1654. // The existing partially encloses the candidate - but
  1655. // not on the bottom.
  1656. //
  1657. // 100,100
  1658. // +----------------------+
  1659. // | Exist |
  1660. // | |
  1661. // | 130,130 |
  1662. // | +--------+ |
  1663. // | | | |
  1664. // | | | |
  1665. // | | Cand | |
  1666. // | | | |
  1667. // | | | |
  1668. // | | | |
  1669. // +-----+--------+-------+
  1670. // | | 200,200
  1671. // | |
  1672. // | |
  1673. // +--------+170,230
  1674. //
  1675. // Adjust the candidate rectangle to be the non-
  1676. // overlapped portion.
  1677. //
  1678. //
  1679. // 100,100
  1680. // +----------------------+
  1681. // | |
  1682. // | |
  1683. // | |
  1684. // | |
  1685. // | |
  1686. // | Exist |
  1687. // | |
  1688. // | |
  1689. // | |
  1690. // | |
  1691. // +----------------------+
  1692. // 130,201+---------+ 200,200
  1693. // | |
  1694. // | Cand |
  1695. // | |
  1696. // +---------+170,230
  1697. //
  1698. // Because this affects the candidate, restart the
  1699. // comparisons to check for overlaps between the
  1700. // adjusted candidate and other existing rectangles.
  1701. //
  1702. //
  1703. TRACE_OUT(( "OL_PART_ENCLOSES_YMAX - %d", iExist));
  1704. pCand->top = g_baBounds[iExist].Coord.bottom + 1;
  1705. fResetRects = TRUE;
  1706. break;
  1707. case OL_SPLIT_X:
  1708. //
  1709. // The existing overlaps the candicate, but neither can
  1710. // be merged or adjusted.
  1711. //
  1712. // 100,100
  1713. // +--------+
  1714. // | |
  1715. // 70,130 | Exist |
  1716. // +-----+--------+------+
  1717. // | | | |
  1718. // | | | |
  1719. // | Cand| | |
  1720. // | | | |
  1721. // | | | |
  1722. // +-----+--------+------+180,160
  1723. // | |
  1724. // | |
  1725. // +--------+150,200
  1726. //
  1727. // Need to split candidate into left and right halves.
  1728. //
  1729. // Only do a split if there is spare room in the list -
  1730. // because both the split rectangles may need to be
  1731. // added to the list.
  1732. //
  1733. // If there is spare room, split the candidate into a
  1734. // smaller candidate on the left and a new rectangle on
  1735. // the right. Call this routine recursively to handle
  1736. // the new rectangle.
  1737. //
  1738. // 100,100
  1739. // +--------+
  1740. // | |
  1741. // 70,130 | |151,130
  1742. // +----+| |+-----+
  1743. // | || || |
  1744. // | || || |
  1745. // |Cand|| Exist || New |
  1746. // | || || |
  1747. // | || || |
  1748. // +----+| |+-----+
  1749. // 99,160| | 180,160
  1750. // | |
  1751. // +--------+150,200
  1752. //
  1753. // After the recursion, because the candidate has
  1754. // changed, restart the comparisons to check for
  1755. // overlaps between the adjusted candidate and other
  1756. // existing rectangles.
  1757. //
  1758. //
  1759. TRACE_OUT(( "OL_SPLIT_X - %d", iExist));
  1760. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1761. (level < ADDR_RECURSE_LIMIT))
  1762. {
  1763. rectNew.left = g_baBounds[iExist].Coord.right + 1;
  1764. rectNew.right = pCand->right;
  1765. rectNew.top = pCand->top;
  1766. rectNew.bottom = pCand->bottom;
  1767. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1768. TRACE_OUT(( "*** RECURSION ***"));
  1769. BAAddRect(&rectNew, level);
  1770. TRACE_OUT(( "*** RETURN ***"));
  1771. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1772. {
  1773. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1774. DC_QUIT;
  1775. }
  1776. fResetRects = TRUE;
  1777. }
  1778. break;
  1779. case OL_SPLIT_Y:
  1780. //
  1781. // The existing overlaps the candicate, but neither can
  1782. // be merged or adjusted.
  1783. //
  1784. // 100,100
  1785. // +--------+
  1786. // | |
  1787. // 70,130 | Cand |
  1788. // +-----+--------+------+
  1789. // | | | |
  1790. // | | | |
  1791. // |Exist| | |
  1792. // | | | |
  1793. // | | | |
  1794. // +-----+--------+------+180,160
  1795. // | |
  1796. // | |
  1797. // +--------+150,200
  1798. //
  1799. // Need to split candidate into top and bottom halves.
  1800. //
  1801. // Only do a split if there is spare room in the list -
  1802. // because both the split rectangles may need to be
  1803. // added to the list.
  1804. //
  1805. // If there is spare room, split the candidate into a
  1806. // smaller candidate on the top and a new rectangle on
  1807. // the bottom. Call this routine recursively to handle
  1808. // the new rectangle.
  1809. //
  1810. // 100,100
  1811. // +--------+
  1812. // | Cand |
  1813. // 70,130 +--------+150,129
  1814. // +---------------------+
  1815. // | |
  1816. // | |
  1817. // | |
  1818. // | |
  1819. // | |
  1820. // +---------------------+180,160
  1821. // 100,161+--------+
  1822. // | New |
  1823. // +--------+150,200
  1824. //
  1825. // After the recursion, because the candidate has
  1826. // changed, restart the comparisons to check for
  1827. // overlaps between the adjusted candidate and other
  1828. // existing rectangles.
  1829. //
  1830. //
  1831. TRACE_OUT(( "OL_SPLIT_Y - %d", iExist));
  1832. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1833. (level < ADDR_RECURSE_LIMIT))
  1834. {
  1835. rectNew.left = pCand->left;
  1836. rectNew.right = pCand->right;
  1837. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  1838. rectNew.bottom = pCand->bottom;
  1839. pCand->bottom = g_baBounds[iExist].Coord.top - 1;
  1840. TRACE_OUT(( "*** RECURSION ***"));
  1841. BAAddRect(&rectNew, level);
  1842. TRACE_OUT(( "*** RETURN ***"));
  1843. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1844. {
  1845. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1846. DC_QUIT;
  1847. }
  1848. fResetRects = TRUE;
  1849. }
  1850. break;
  1851. case OL_SPLIT_XMIN_YMIN:
  1852. //
  1853. // The existing overlaps the candicate, but neither can
  1854. // be merged or adjusted.
  1855. //
  1856. // 100,100
  1857. // +---------------+
  1858. // | Cand |
  1859. // | |
  1860. // | |
  1861. // | 150,150 |
  1862. // | +-------+-----+
  1863. // | | | |
  1864. // | | | |
  1865. // | | | |
  1866. // | | | |
  1867. // | | | |
  1868. // +-------+-------+ |
  1869. // | 200,200 |
  1870. // | |
  1871. // | Exist |
  1872. // | |
  1873. // +-------------+
  1874. // 250,250
  1875. //
  1876. // Need to split candidate into top and left pieces.
  1877. //
  1878. // Only do a split if there is spare room in the list -
  1879. // because both the split rectangles may need to be
  1880. // added to the list.
  1881. //
  1882. // If there is spare room, split the candidate into a
  1883. // smaller candidate on the left and a new rectangle on
  1884. // the top. Call this routine recursively to handle
  1885. // the new rectangle.
  1886. //
  1887. // 100,100 151,100
  1888. // +-------+-------+
  1889. // | | |
  1890. // | | New |
  1891. // | | |
  1892. // | | |200,149
  1893. // | +-------+-----+
  1894. // | Cand |150,150 |
  1895. // | | |
  1896. // | | |
  1897. // | | |
  1898. // | | Exist |
  1899. // +-------+ |
  1900. // 150,200| |
  1901. // | |
  1902. // | |
  1903. // | |
  1904. // +-------------+
  1905. // 250,250
  1906. //
  1907. // After the recursion, because the candidate has
  1908. // changed, restart the comparisons to check for
  1909. // overlaps between the adjusted candidate and other
  1910. // existing rectangles.
  1911. //
  1912. //
  1913. TRACE_OUT(( "OL_SPLIT_XMIN_YMIN - %d", iExist));
  1914. if ( g_baRectsUsed < BA_NUM_RECTS )
  1915. {
  1916. rectNew.left = g_baBounds[iExist].Coord.left;
  1917. rectNew.right = pCand->right;
  1918. rectNew.top = pCand->top;
  1919. rectNew.bottom = g_baBounds[iExist].Coord.top - 1;
  1920. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1921. TRACE_OUT(( "*** RECURSION ***"));
  1922. BAAddRect(&rectNew, level);
  1923. TRACE_OUT(( "*** RETURN ***"));
  1924. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1925. {
  1926. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1927. DC_QUIT;
  1928. }
  1929. fResetRects = TRUE;
  1930. }
  1931. break;
  1932. case OL_SPLIT_XMAX_YMIN:
  1933. //
  1934. // The existing overlaps the candicate, but neither can
  1935. // be merged or adjusted.
  1936. //
  1937. // 150,100
  1938. // +---------------+
  1939. // | |
  1940. // | Cand |
  1941. // 100,150 | |
  1942. // +------+--------+ |
  1943. // | | | |
  1944. // | | | |
  1945. // | | | |
  1946. // | | | |
  1947. // | | | |
  1948. // | | | |
  1949. // | +--------+------+
  1950. // | | 250,200
  1951. // | Exist |
  1952. // | |
  1953. // +---------------+
  1954. // 200,250
  1955. //
  1956. // Need to split candidate into top and right pieces.
  1957. //
  1958. // Only do a split if there is spare room in the list -
  1959. // because both the split rectangles may need to be
  1960. // added to the list.
  1961. //
  1962. // If there is spare room, split the candidate into a
  1963. // smaller candidate on the right and a new rectangle
  1964. // on the top. Call this routine recursively to handle
  1965. // the new rectangle.
  1966. //
  1967. // 150,100 201,100
  1968. // +--------+------+
  1969. // | New | |
  1970. // | | |
  1971. // 100,150 | 200,149| |
  1972. // +------+--------+ |
  1973. // | | Cand |
  1974. // | | |
  1975. // | | |
  1976. // | | |
  1977. // | Exist | |
  1978. // | | |
  1979. // | +------+
  1980. // | | 250,200
  1981. // | |
  1982. // | |
  1983. // +---------------+
  1984. // 200,250
  1985. //
  1986. // After the recursion, because the candidate has
  1987. // changed, restart the comparisons to check for
  1988. // overlaps between the adjusted candidate and other
  1989. // existing rectangles.
  1990. //
  1991. //
  1992. TRACE_OUT(( "OL_SPLIT_XMAX_YMIN - %d", iExist));
  1993. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1994. (level < ADDR_RECURSE_LIMIT))
  1995. {
  1996. rectNew.left = pCand->left;
  1997. rectNew.right = g_baBounds[iExist].Coord.right;
  1998. rectNew.top = pCand->top;
  1999. rectNew.bottom = g_baBounds[iExist].Coord.top - 1;
  2000. pCand->left = g_baBounds[iExist].Coord.right + 1;
  2001. TRACE_OUT(( "*** RECURSION ***"));
  2002. BAAddRect(&rectNew, level);
  2003. TRACE_OUT(( "*** RETURN ***"));
  2004. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  2005. {
  2006. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  2007. DC_QUIT;
  2008. }
  2009. fResetRects = TRUE;
  2010. }
  2011. break;
  2012. case OL_SPLIT_XMIN_YMAX:
  2013. //
  2014. // The existing overlaps the candicate, but neither can
  2015. // be merged or adjusted.
  2016. //
  2017. // 150,100
  2018. // +---------------+
  2019. // | |
  2020. // | Exist |
  2021. // 100,150 | |
  2022. // +------+--------+ |
  2023. // | | | |
  2024. // | | | |
  2025. // | | | |
  2026. // | | | |
  2027. // | | | |
  2028. // | | | |
  2029. // | +--------+------+
  2030. // | | 250,200
  2031. // | Cand |
  2032. // | |
  2033. // +---------------+
  2034. // 200,250
  2035. //
  2036. // Need to split candidate into left and bottom pieces.
  2037. //
  2038. // Only do a split if there is spare room in the list -
  2039. // because both the split rectangles may need to be
  2040. // added to the list.
  2041. //
  2042. // If there is spare room, split the candidate into a
  2043. // smaller candidate on the left and a new rectangle on
  2044. // the bottom. Call this routine recursively to handle
  2045. // the new rectangle.
  2046. //
  2047. // 150,100
  2048. // +---------------+
  2049. // | |
  2050. // | |
  2051. // 100,150 | |
  2052. // +------+ |
  2053. // | | |
  2054. // | | |
  2055. // | | |
  2056. // | | |
  2057. // | Cand | |
  2058. // | | |
  2059. // | +--------+------+
  2060. // | |151,200 | 250,200
  2061. // | | |
  2062. // | | New |
  2063. // +------+--------+
  2064. // 149,250 200,250
  2065. //
  2066. // After the recursion, because the candidate has
  2067. // changed, restart the comparisons to check for
  2068. // overlaps between the adjusted candidate and other
  2069. // existing rectangles.
  2070. //
  2071. //
  2072. TRACE_OUT(( "OL_SPLIT_XMIN_YMAX - %d", iExist));
  2073. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  2074. (level < ADDR_RECURSE_LIMIT))
  2075. {
  2076. rectNew.left = g_baBounds[iExist].Coord.left;
  2077. rectNew.right = pCand->right;
  2078. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  2079. rectNew.bottom = pCand->bottom;
  2080. pCand->right = g_baBounds[iExist].Coord.left - 1;
  2081. TRACE_OUT(( "*** RECURSION ***"));
  2082. BAAddRect(&rectNew, level);
  2083. TRACE_OUT(( "*** RETURN ***"));
  2084. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  2085. {
  2086. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  2087. DC_QUIT;
  2088. }
  2089. fResetRects = TRUE;
  2090. }
  2091. break;
  2092. case OL_SPLIT_XMAX_YMAX:
  2093. //
  2094. // The existing overlaps the candicate, but neither can
  2095. // be merged or adjusted.
  2096. //
  2097. // 100,100
  2098. // +---------------+
  2099. // | Exist |
  2100. // | |
  2101. // | |
  2102. // | 150,150 |
  2103. // | +-------+-----+
  2104. // | | | |
  2105. // | | | |
  2106. // | | | |
  2107. // | | | |
  2108. // | | | |
  2109. // +-------+-------+ |
  2110. // | 200,200 |
  2111. // | |
  2112. // | Cand |
  2113. // | |
  2114. // +-------------+
  2115. // 250,250
  2116. //
  2117. // Need to split candidate into bottom and right pieces.
  2118. //
  2119. // Only do a split if there is spare room in the list -
  2120. // because both the split rectangles may need to be
  2121. // added to the list.
  2122. //
  2123. // If there is spare room, split the candidate into a
  2124. // smaller candidate on the right and a new rectangle
  2125. // on the bottom. Call this routine recursively to
  2126. // handle the new rectangle.
  2127. //
  2128. // 100,100
  2129. // +---------------+
  2130. // | |
  2131. // | |
  2132. // | |
  2133. // | |201,150
  2134. // | Exist +-----+
  2135. // | | |
  2136. // | | |
  2137. // | | |
  2138. // | |Cand |
  2139. // | 200,200| |
  2140. // +-------+-------+ |
  2141. // 150,201| | |
  2142. // | | |
  2143. // | New | |
  2144. // | | |
  2145. // +-------+-----+
  2146. // 200,250 250,250
  2147. //
  2148. // After the recursion, because the candidate has
  2149. // changed, restart the comparisons to check for
  2150. // overlaps between the adjusted candidate and other
  2151. // existing rectangles.
  2152. //
  2153. //
  2154. TRACE_OUT(( "OL_SPLIT_XMAX_YMAX - %d", iExist));
  2155. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  2156. (level < ADDR_RECURSE_LIMIT))
  2157. {
  2158. rectNew.left = pCand->left;
  2159. rectNew.right = g_baBounds[iExist].Coord.right;
  2160. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  2161. rectNew.bottom = pCand->bottom;
  2162. pCand->left = g_baBounds[iExist].Coord.right + 1;
  2163. TRACE_OUT(( "*** RECURSION ***"));
  2164. BAAddRect(&rectNew, level);
  2165. TRACE_OUT(( "*** RETURN ***"));
  2166. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  2167. {
  2168. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  2169. DC_QUIT;
  2170. }
  2171. fResetRects = TRUE;
  2172. }
  2173. break;
  2174. default:
  2175. //
  2176. // This should not happen.
  2177. //
  2178. ERROR_OUT(( "Unrecognised overlap case-%d",OverlapType));
  2179. break;
  2180. }
  2181. iExist = (fResetRects) ? g_baFirstRect :
  2182. g_baBounds[iExist].iNext;
  2183. }
  2184. //
  2185. // Arriving here means that no overlap was found between the
  2186. // candidate and the existing rectangles.
  2187. //
  2188. // - If the candidate is the original rectangle, add it to the
  2189. // list.
  2190. // - If the candidate is an existing rectangle, it is already in
  2191. // the list.
  2192. //
  2193. if ( fRectToAdd )
  2194. {
  2195. BAAddRectList(pCand);
  2196. }
  2197. //
  2198. // The compare and add processing above is allowed to add a
  2199. // rectangle to the list when there are already BA_NUM_RECTS
  2200. // (eg. when doing a split or when there is no overlap at all with
  2201. // the existing rectangles) - and there is an extra slot for that
  2202. // purpose.
  2203. //
  2204. // If we now have more than BA_NUM_RECTS rectangles, do a
  2205. // forced merge, so that the next call to this routine has a spare
  2206. // slot.
  2207. //
  2208. //
  2209. fRectMerged = ( g_baRectsUsed > BA_NUM_RECTS );
  2210. if ( fRectMerged )
  2211. {
  2212. //
  2213. // Start looking for merged rectangles.
  2214. //
  2215. // For each rectangle in the list, compare it with the others,
  2216. // and Determine cost of merging.
  2217. //
  2218. // We want to merge the two rectangles with the minimum
  2219. // area difference, ie that will produce a merged
  2220. // rectangle that covers the least superfluous screen
  2221. // area.
  2222. //
  2223. // Note that we calculate the areas of the rectangles here
  2224. // (rather than on the fly as they are created/ manipulated in
  2225. // the loop), as the statistics show that forced merges occur
  2226. // very much less frequently than non-forced manipulations (ie
  2227. // splits, adds etc.
  2228. //
  2229. //
  2230. bestMergeIncrease = 0x7FFFFFFF;
  2231. for ( iExist = g_baFirstRect;
  2232. iExist != BA_INVALID_RECT_INDEX;
  2233. iExist = g_baBounds[iExist].iNext )
  2234. {
  2235. g_baBounds[iExist].Area =
  2236. COM_SizeOfRectInclusive(&g_baBounds[iExist].Coord);
  2237. }
  2238. #ifdef _DEBUG
  2239. iBestMerge1 = BA_INVALID_RECT_INDEX;
  2240. iBestMerge2 = BA_INVALID_RECT_INDEX;
  2241. #endif
  2242. for ( iExist = g_baFirstRect;
  2243. iExist != BA_INVALID_RECT_INDEX;
  2244. iExist = g_baBounds[iExist].iNext )
  2245. {
  2246. for ( iTmp = g_baBounds[iExist].iNext;
  2247. iTmp != BA_INVALID_RECT_INDEX;
  2248. iTmp = g_baBounds[iTmp].iNext )
  2249. {
  2250. rectNew.left = min( g_baBounds[iExist].Coord.left,
  2251. g_baBounds[iTmp].Coord.left );
  2252. rectNew.top = min( g_baBounds[iExist].Coord.top,
  2253. g_baBounds[iTmp].Coord.top );
  2254. rectNew.right = max( g_baBounds[iExist].Coord.right,
  2255. g_baBounds[iTmp].Coord.right );
  2256. rectNew.bottom = max( g_baBounds[iExist].Coord.bottom,
  2257. g_baBounds[iTmp].Coord.bottom );
  2258. mergeIncrease = COM_SizeOfRectInclusive(&rectNew) -
  2259. g_baBounds[iExist].Area - g_baBounds[iTmp].Area;
  2260. if (bestMergeIncrease > mergeIncrease)
  2261. {
  2262. iBestMerge1 = iExist;
  2263. iBestMerge2 = iTmp;
  2264. bestMergeIncrease = mergeIncrease;
  2265. }
  2266. }
  2267. }
  2268. ASSERT(iBestMerge1 != BA_INVALID_RECT_INDEX);
  2269. ASSERT(iBestMerge2 != BA_INVALID_RECT_INDEX);
  2270. //
  2271. // Now do the merge.
  2272. //
  2273. // We recalculate the size of the merged rectangle here -
  2274. // alternatively we could remember the size of the best so far
  2275. // in the loop above. The trade off is between calculating
  2276. // twice or copying at least once but probably more than once
  2277. // as we find successively better merges.
  2278. //
  2279. TRACE_OUT(("BestMerge1 %d, (%d,%d,%d,%d)", iBestMerge1,
  2280. g_baBounds[iBestMerge1].Coord.left,
  2281. g_baBounds[iBestMerge1].Coord.top,
  2282. g_baBounds[iBestMerge1].Coord.right,
  2283. g_baBounds[iBestMerge1].Coord.bottom ));
  2284. TRACE_OUT(("BestMerge2 %d, (%d,%d,%d,%d)", iBestMerge2,
  2285. g_baBounds[iBestMerge2].Coord.left,
  2286. g_baBounds[iBestMerge2].Coord.top,
  2287. g_baBounds[iBestMerge2].Coord.right,
  2288. g_baBounds[iBestMerge2].Coord.bottom ));
  2289. g_baBounds[iBestMerge1].Coord.left =
  2290. min( g_baBounds[iBestMerge1].Coord.left,
  2291. g_baBounds[iBestMerge2].Coord.left );
  2292. g_baBounds[iBestMerge1].Coord.top =
  2293. min( g_baBounds[iBestMerge1].Coord.top,
  2294. g_baBounds[iBestMerge2].Coord.top );
  2295. g_baBounds[iBestMerge1].Coord.right =
  2296. max( g_baBounds[iBestMerge1].Coord.right,
  2297. g_baBounds[iBestMerge2].Coord.right );
  2298. g_baBounds[iBestMerge1].Coord.bottom =
  2299. max( g_baBounds[iBestMerge1].Coord.bottom,
  2300. g_baBounds[iBestMerge2].Coord.bottom );
  2301. //
  2302. // Remove the second best merge.
  2303. //
  2304. BA_RemoveRectList(&(g_baBounds[iBestMerge2].Coord));
  2305. //
  2306. // The best merged rectangle becomes the candidate, and we fall
  2307. // g_back to the head of the comparison loop to start again.
  2308. //
  2309. pCand = &(g_baBounds[iBestMerge1].Coord);
  2310. iLastMerge = iBestMerge1;
  2311. fRectToAdd = FALSE;
  2312. }
  2313. } while ( fRectMerged );
  2314. DC_EXIT_POINT:
  2315. DebugExitBOOL(BAAddRect, rc);
  2316. return(rc);
  2317. }