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.

2475 lines
101 KiB

  1. //
  2. // BA.C
  3. // Bounds Accumulator
  4. //
  5. // Copyright(c) Microsoft 1997-
  6. //
  7. #include <as16.h>
  8. //
  9. // BA_DDProcessRequest()
  10. // Handles BA escapes
  11. //
  12. BOOL BA_DDProcessRequest
  13. (
  14. UINT fnEscape,
  15. LPOSI_ESCAPE_HEADER pResult,
  16. DWORD cbResult
  17. )
  18. {
  19. BOOL rc = TRUE;
  20. LPBA_BOUNDS_INFO pBoundsInfo;
  21. UINT i;
  22. RECT rect;
  23. DebugEntry(BA_DDProcessRequest);
  24. switch (fnEscape)
  25. {
  26. case BA_ESC_GET_BOUNDS:
  27. {
  28. //
  29. // The share core is calling us to get the current bounds
  30. // (presumably to try to send them). While the share core is
  31. // processing the bounds, we reset the bounds, but take a copy
  32. // first to use for spoiling orders by SDA. When the share
  33. // core has completed processing the bounds, it will call us
  34. // again with a BA_ESC_RETURN_BOUNDS escape (even if it has
  35. // sent all the bounds).
  36. //
  37. // So, we have to:
  38. // - return the bounds to the share core
  39. // - set up the spoiling rects to be these bounds
  40. // - clear our main bounds.
  41. //
  42. //
  43. // This will copy the current bounds to the caller's buffer and
  44. // clear our current bounds.
  45. // NOTE: We keep these in globals because the caller will shortly
  46. // call us to return any unsent bounds rects.
  47. //
  48. BA_CopyBounds(g_baSpoilingRects, &g_baNumSpoilingRects, TRUE);
  49. //
  50. // Return the bounds info to the share core
  51. //
  52. if (g_baNumSpoilingRects)
  53. {
  54. TRACE_OUT(( "Returning %d rects to share core", g_baNumSpoilingRects));
  55. }
  56. pBoundsInfo = (LPBA_BOUNDS_INFO)pResult;
  57. pBoundsInfo->numRects = g_baNumSpoilingRects;
  58. for (i = 0; i < g_baNumSpoilingRects; i++)
  59. {
  60. RECT_TO_RECTL(&g_baSpoilingRects[i], &pBoundsInfo->rects[i]);
  61. }
  62. }
  63. break;
  64. case BA_ESC_RETURN_BOUNDS:
  65. {
  66. //
  67. // The share core has completed its processing of the bounds
  68. // which we passed on the BA_ESC_GET_BOUNDS escape. We have to
  69. // reset the spoiling rectangles and add any bounds which the
  70. // share core failed to process into our current bounds.
  71. //
  72. //
  73. // To reset the spoiling bounds we just have to reset the
  74. // number of bounds.
  75. //
  76. g_baNumSpoilingRects = 0;
  77. //
  78. // Now add the share core's bounds into our current bounds
  79. //
  80. pBoundsInfo = (LPBA_BOUNDS_INFO)pResult;
  81. if (pBoundsInfo->numRects)
  82. {
  83. TRACE_OUT(( "Received %d rects from share core",
  84. pBoundsInfo->numRects));
  85. }
  86. for (i = 0 ; i < pBoundsInfo->numRects ; i++)
  87. {
  88. RECTL_TO_RECT(&pBoundsInfo->rects[i], &rect);
  89. TRACE_OUT(( "Rect %d, {%d, %d, %d, %d}",
  90. i, rect.left, rect.top, rect.right, rect.bottom));
  91. BA_AddScreenData(&rect);
  92. }
  93. }
  94. break;
  95. default:
  96. {
  97. ERROR_OUT(( "Unrecognised BA escape"));
  98. rc = FALSE;
  99. }
  100. break;
  101. }
  102. DebugExitBOOL(BA_DDProcessRequest, rc);
  103. return(rc);
  104. }
  105. //
  106. // BA_DDInit - see ba.h for description.
  107. //
  108. void BA_DDInit(void)
  109. {
  110. DebugEntry(BA_Init);
  111. BA_ResetBounds();
  112. DebugExitVOID(BA_Init);
  113. }
  114. //
  115. // This gets a current version of our bound rect list, and clears it
  116. // afterwards if requested.
  117. //
  118. void BA_CopyBounds
  119. (
  120. LPRECT pRects,
  121. LPUINT pNumRects,
  122. BOOL fReset
  123. )
  124. {
  125. UINT i;
  126. #ifdef DEBUG
  127. UINT cRects = 0;
  128. #endif
  129. DebugEntry(BA_CopyBounds);
  130. *pNumRects = g_baRectsUsed;
  131. //
  132. // A return with *pNumRects as zero is an OK return - it just says
  133. // no bounds have been accumulated since the last call.
  134. //
  135. if ( *pNumRects != 0)
  136. {
  137. //
  138. // We can return the bounds in any order - we don't care how we
  139. // order the SDA rectangles.
  140. //
  141. // Also note that we must compare BA_NUM_RECTS + 1 sets of
  142. // rectangles because that's the number actually used by the add
  143. // rectangle code and while it guarantees that it will only use
  144. // BA_NUM_RECTS rectangles, it does not guarantee that the last
  145. // element in the array is the merge rectangle.
  146. //
  147. for (i = 0; i <= BA_NUM_RECTS; i++)
  148. {
  149. if (g_baBounds[i].InUse)
  150. {
  151. TRACE_OUT(("Found rect: {%04d,%04d,%04d,%04d}",
  152. g_baBounds[i].Coord.left, g_baBounds[i].Coord.top,
  153. g_baBounds[i].Coord.right, g_baBounds[i].Coord.bottom));
  154. *pRects = g_baBounds[i].Coord;
  155. pRects++;
  156. #ifdef DEBUG
  157. cRects++;
  158. #endif
  159. }
  160. }
  161. //
  162. // Check for self-consistency
  163. //
  164. ASSERT(cRects == *pNumRects);
  165. if (fReset)
  166. BA_ResetBounds();
  167. }
  168. DebugExitVOID(BACopyBounds);
  169. }
  170. //
  171. //
  172. // BA_AddScreenData(..)
  173. //
  174. // Adds the specified rectangle to the current Screen Data Area.
  175. //
  176. // Called by the GDI interception code for orders that it cannot send as
  177. // orders.
  178. //
  179. // NOTE that the rectangle is inclusive coords
  180. //
  181. //
  182. void BA_AddScreenData(LPRECT pRect)
  183. {
  184. RECT preRects[BA_NUM_RECTS];
  185. RECT postRects[BA_NUM_RECTS];
  186. UINT numPreRects;
  187. UINT numPostRects;
  188. UINT i;
  189. DebugEntry(BA_AddScreenData);
  190. //
  191. // Check that the caller has passed a valid rectangle. If not, do a
  192. // trace alert, and then return immediately (as an invalid rectangle
  193. // shouldn't contribute to the accumulated bounds) - but report an OK
  194. // return code, so we keep running.
  195. //
  196. if ((pRect->right < pRect->left) ||
  197. (pRect->bottom < pRect->top) )
  198. {
  199. //
  200. // NOTE: This will happen when the visrgn of a DC clips out the
  201. // output, so the drawing bounds are empty, but the output
  202. // 'succeeded'. BUT WE SHOULD NEVER GET A RECT THAT IS LESS THAN
  203. // EMPTY--if so, it means the right/left or bottom/top coords got
  204. // mistakenly flipped.
  205. //
  206. ASSERT(pRect->right >= pRect->left-1);
  207. ASSERT(pRect->bottom >= pRect->top-1);
  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. hmemcpy(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. LONG bestMergeIncrease;
  900. LONG 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. iExist = g_baBounds[iExist].iNext;
  951. continue;
  952. }
  953. //
  954. // Switch on the overlap type (see Overlap routine).
  955. //
  956. OverlapType = BAOverlap(&(g_baBounds[iExist].Coord), pCand);
  957. switch (OverlapType)
  958. {
  959. case OL_NONE:
  960. //
  961. // No overlap.
  962. //
  963. break;
  964. case OL_MERGE_XMIN:
  965. //
  966. // - either the candidate abutts the existing rectangle
  967. // on the left
  968. //
  969. // 10,10 51,10
  970. // +----------++----------+
  971. // | || |
  972. // | || |
  973. // | || |
  974. // | Cand || Exist |
  975. // | || |
  976. // | || |
  977. // | || |
  978. // +----------++----------+
  979. // 50,50 100,50
  980. //
  981. // - or the candidate overlaps the existing on the left
  982. // and can be merged
  983. //
  984. // 10,10 40,10
  985. // +-------+--+------+
  986. // | | | |
  987. // | | | |
  988. // | | | |
  989. // | Cand | |Exist |
  990. // | | | |
  991. // | | | |
  992. // | | | |
  993. // +-------+--+------+
  994. // 50,50 90,50
  995. //
  996. // If the candidate is the original, merge the
  997. // candidate into the existing, and make the existing
  998. // the new candidate.
  999. //
  1000. // If this is a merge of two existing rectangles (ie
  1001. // the candidate is the result of a merge), merge the
  1002. // overlapping existing into the candidate (the last
  1003. // merged) and remove the existing.
  1004. //
  1005. // For both, start the comparisons again with the new
  1006. // candidate.
  1007. //
  1008. if ( fRectToAdd )
  1009. {
  1010. g_baBounds[iExist].Coord.left = pCand->left;
  1011. pCand = &(g_baBounds[iExist].Coord);
  1012. fRectToAdd = FALSE;
  1013. iLastMerge = iExist;
  1014. }
  1015. else
  1016. {
  1017. pCand->right = g_baBounds[iExist].Coord.right;
  1018. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1019. }
  1020. fResetRects = TRUE;
  1021. break;
  1022. case OL_MERGE_XMAX:
  1023. //
  1024. // - either the candidate abutts the existing rectangle
  1025. // on the right
  1026. //
  1027. // 10,10 51,10
  1028. // +----------++----------+
  1029. // | || |
  1030. // | || |
  1031. // | || |
  1032. // | Exist || Cand |
  1033. // | || |
  1034. // | || |
  1035. // | || |
  1036. // +----------++----------+
  1037. // 50,50 100,50
  1038. //
  1039. // - or the candidate overlaps the existing on the right
  1040. // and can be merged
  1041. //
  1042. // 10,10 40,10
  1043. // +-------+--+------+
  1044. // | | | |
  1045. // | | | |
  1046. // | | | |
  1047. // | Exist | | Cand |
  1048. // | | | |
  1049. // | | | |
  1050. // | | | |
  1051. // +-------+--+------+
  1052. // 50,50 90,50
  1053. //
  1054. // If the candidate is the original, merge the
  1055. // candidate into the existing, and make the existing
  1056. // the new candidate.
  1057. //
  1058. // If this is a merge of two existing rectangles (ie
  1059. // the candidate is the result of a merge), merge the
  1060. // overlapping existing into the candidate (the last
  1061. // merged) and remove the existing.
  1062. //
  1063. // For both, start the comparisons again with the new
  1064. // candidate.
  1065. //
  1066. if ( fRectToAdd )
  1067. {
  1068. g_baBounds[iExist].Coord.right = pCand->right;
  1069. pCand = &(g_baBounds[iExist].Coord);
  1070. fRectToAdd = FALSE;
  1071. iLastMerge = iExist;
  1072. }
  1073. else
  1074. {
  1075. pCand->left = g_baBounds[iExist].Coord.left;
  1076. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1077. }
  1078. fResetRects = TRUE;
  1079. break;
  1080. case OL_MERGE_YMIN:
  1081. //
  1082. // - either the candidate abutts the existing rectangle
  1083. // on the top
  1084. //
  1085. // 10,10
  1086. // +---------+
  1087. // | |
  1088. // | |
  1089. // | |
  1090. // | Cand |
  1091. // | |
  1092. // | |
  1093. // | |
  1094. // +---------+50,50
  1095. // 10,51+---------+
  1096. // | |
  1097. // | |
  1098. // | |
  1099. // | Exist |
  1100. // | |
  1101. // | |
  1102. // | |
  1103. // +---------+50,100
  1104. //
  1105. // - or the candidate overlaps the existing on the top
  1106. // and can be merged
  1107. //
  1108. // 10,10
  1109. // +---------+
  1110. // | |
  1111. // | |
  1112. // | |
  1113. // | Cand |
  1114. // | |
  1115. // | |
  1116. // Exist 10,40+---------+
  1117. // | |
  1118. // | |
  1119. // | |
  1120. // +---------+50,60 Cand
  1121. // | |
  1122. // | Exist |
  1123. // | |
  1124. // | |
  1125. // | |
  1126. // +---------+50,100
  1127. //
  1128. // If the candidate is the original, merge the
  1129. // candidate into the existing, and make the existing
  1130. // the new candidate.
  1131. //
  1132. // If this is a merge of two existing rectangles (ie
  1133. // the candidate is the result of a merge), merge the
  1134. // overlapping existing into the candidate (the last
  1135. // merged) and remove the existing.
  1136. //
  1137. // For both, start the comparisons again with the new
  1138. // candidate.
  1139. //
  1140. if ( fRectToAdd )
  1141. {
  1142. g_baBounds[iExist].Coord.top = pCand->top;
  1143. pCand = &(g_baBounds[iExist].Coord);
  1144. fRectToAdd = FALSE;
  1145. iLastMerge = iExist;
  1146. }
  1147. else
  1148. {
  1149. pCand->bottom = g_baBounds[iExist].Coord.bottom;
  1150. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1151. }
  1152. fResetRects = TRUE;
  1153. break;
  1154. case OL_MERGE_YMAX:
  1155. //
  1156. // - either the candidate abutts the existing rectangle
  1157. // from below
  1158. //
  1159. // 10,10
  1160. // +---------+
  1161. // | |
  1162. // | |
  1163. // | |
  1164. // | Exist |
  1165. // | |
  1166. // | |
  1167. // | |
  1168. // +---------+50,50
  1169. // 10,51+---------+
  1170. // | |
  1171. // | |
  1172. // | |
  1173. // | Cand |
  1174. // | |
  1175. // | |
  1176. // | |
  1177. // +---------+50,100
  1178. //
  1179. // - or the candidate overlaps the existing from below
  1180. // and can be merged
  1181. //
  1182. // 10,10
  1183. // +---------+
  1184. // | |
  1185. // | |
  1186. // | |
  1187. // | Exist |
  1188. // | |
  1189. // | |
  1190. // Cand 10,40+---------+
  1191. // | |
  1192. // | |
  1193. // | |
  1194. // +---------+50,60 Exist
  1195. // | |
  1196. // | Cand |
  1197. // | |
  1198. // | |
  1199. // | |
  1200. // +---------+50,100
  1201. //
  1202. // If the candidate is the original, merge the
  1203. // candidate into the existing, and make the existing
  1204. // the new candidate.
  1205. //
  1206. // If this is a merge of two existing rectangles (ie
  1207. // the candidate is the result of a merge), merge the
  1208. // overlapping existing into the candidate (the last
  1209. // merged) and remove the existing.
  1210. //
  1211. // For both, start the comparisons again with the new
  1212. // candidate.
  1213. //
  1214. if ( fRectToAdd )
  1215. {
  1216. g_baBounds[iExist].Coord.bottom = pCand->bottom;
  1217. pCand = &(g_baBounds[iExist].Coord);
  1218. fRectToAdd = FALSE;
  1219. iLastMerge = iExist;
  1220. }
  1221. else
  1222. {
  1223. pCand->top = g_baBounds[iExist].Coord.top;
  1224. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1225. }
  1226. fResetRects = TRUE;
  1227. break;
  1228. case OL_ENCLOSED:
  1229. //
  1230. // The existing is enclosed by the candidate.
  1231. //
  1232. // 100,100
  1233. // +----------------------+
  1234. // | Cand |
  1235. // | |
  1236. // | 130,130 |
  1237. // | +------------+ |
  1238. // | | | |
  1239. // | | | |
  1240. // | | Exist | |
  1241. // | | | |
  1242. // | +------------+ |
  1243. // | 170,170 |
  1244. // | |
  1245. // +----------------------+
  1246. // 200,200
  1247. //
  1248. // If the candidate is the original, replace the
  1249. // existing by the candidate, and make the new existing
  1250. // the new candidate.
  1251. //
  1252. // If the candidate is an existing rectangle, remove
  1253. // the other existing rectangle.
  1254. //
  1255. // For both, start the comparisons again with the new
  1256. // candidate.
  1257. //
  1258. if ( fRectToAdd )
  1259. {
  1260. g_baBounds[iExist].Coord = *pCand;
  1261. pCand = &(g_baBounds[iExist].Coord);
  1262. fRectToAdd = FALSE;
  1263. iLastMerge = iExist;
  1264. }
  1265. else
  1266. {
  1267. BA_RemoveRectList(&(g_baBounds[iExist].Coord));
  1268. }
  1269. fResetRects = TRUE;
  1270. break;
  1271. case OL_PART_ENCLOSED_XMIN:
  1272. //
  1273. // The existing is partially enclosed by the candidate
  1274. // - but not on the right.
  1275. //
  1276. // 100,100
  1277. // +----------------------+
  1278. // | Cand |
  1279. // | |
  1280. // | 130,130 |
  1281. // | +-----------------+---+
  1282. // | | | |
  1283. // | | | |
  1284. // | | Exist | |
  1285. // | | | |
  1286. // | +-----------------+---+
  1287. // | | 220,170
  1288. // | |
  1289. // +----------------------+
  1290. // 200,200
  1291. //
  1292. // Adjust the existing rectangle to be the non-
  1293. // overlapped portion.
  1294. //
  1295. // 100,100
  1296. // +----------------------+
  1297. // | |
  1298. // | |201,130
  1299. // | |+--+
  1300. // | ||E |
  1301. // | ||x |
  1302. // | Cand ||i |
  1303. // | ||s |
  1304. // | ||t |
  1305. // | || |
  1306. // | |+--+
  1307. // | | 220,170
  1308. // +----------------------+
  1309. // 200,200
  1310. //
  1311. // Note that this does not restart the comparisons.
  1312. //
  1313. g_baBounds[iExist].Coord.left = pCand->right + 1;
  1314. break;
  1315. case OL_PART_ENCLOSED_XMAX:
  1316. //
  1317. // The existing is partially enclosed by the candidate
  1318. // - but not on the left.
  1319. //
  1320. // 100,100
  1321. // +----------------------+
  1322. // | Cand |
  1323. // 70,130 | |
  1324. // +-----+---------------+ |
  1325. // | | | |
  1326. // | | | |
  1327. // | | Exist | |
  1328. // | | | |
  1329. // +-----+---------------+ |
  1330. // | 170,170 |
  1331. // | |
  1332. // +----------------------+
  1333. // 200,200
  1334. //
  1335. // Adjust the existing rectangle to be the non-
  1336. // overlapped portion.
  1337. //
  1338. // 100,100
  1339. // +----------------------+
  1340. // 70,130 | |
  1341. // +----+| |
  1342. // | E || |
  1343. // | x || |
  1344. // | i || Cand |
  1345. // | s || |
  1346. // | t || |
  1347. // | || |
  1348. // +----+| |
  1349. // 99,170| |
  1350. // | |
  1351. // +----------------------+
  1352. // 200,200
  1353. //
  1354. // Note that this does not restart the comparisons.
  1355. //
  1356. g_baBounds[iExist].Coord.right = pCand->left - 1;
  1357. break;
  1358. case OL_PART_ENCLOSED_YMIN:
  1359. //
  1360. // The existing is partially enclosed by the candidate
  1361. // - but not on the bottom.
  1362. //
  1363. // 100,100
  1364. // +----------------------+
  1365. // | Cand |
  1366. // | 130,130 |
  1367. // | +--------+ |
  1368. // | | | |
  1369. // | | Exist | |
  1370. // | | | |
  1371. // | | | |
  1372. // | | | |
  1373. // | | | |
  1374. // | | | |
  1375. // +-----+--------+-------+
  1376. // | | 200,200
  1377. // | |
  1378. // | |
  1379. // +--------+170,230
  1380. //
  1381. // Adjust the existing rectangle to be the non-
  1382. // overlapped portion.
  1383. //
  1384. //
  1385. // 100,100
  1386. // +----------------------+
  1387. // | |
  1388. // | |
  1389. // | |
  1390. // | |
  1391. // | |
  1392. // | Cand |
  1393. // | |
  1394. // | |
  1395. // | |
  1396. // | |
  1397. // +----------------------+
  1398. // 130,201+---------+ 200,200
  1399. // | |
  1400. // | Exist |
  1401. // | |
  1402. // +---------+170,230
  1403. //
  1404. // Note that this does not restart the comparisons.
  1405. //
  1406. g_baBounds[iExist].Coord.top = pCand->bottom + 1;
  1407. break;
  1408. case OL_PART_ENCLOSED_YMAX:
  1409. //
  1410. // The existing is partially enclosed by the candidate
  1411. // - but not on the top.
  1412. //
  1413. // 70,130
  1414. // +---------+
  1415. // | |
  1416. // | |
  1417. // 100,100 | |
  1418. // +-----+---------+------+
  1419. // | | | |
  1420. // | | | |
  1421. // | | | |
  1422. // | | | |
  1423. // | | Exist | |
  1424. // | | | |
  1425. // | | | |
  1426. // | +---------+ |
  1427. // | 170,170 |
  1428. // | |
  1429. // | Cand |
  1430. // +----------------------+
  1431. // 200,200
  1432. //
  1433. // Adjust the existing rectangle to be the non-
  1434. // overlapped portion.
  1435. //
  1436. // 70,130
  1437. // +---------+
  1438. // | |
  1439. // | Exist |
  1440. // | |
  1441. // 100,100 +---------+170,99
  1442. // +----------------------+
  1443. // | |
  1444. // | |
  1445. // | |
  1446. // | |
  1447. // | |
  1448. // | Cand |
  1449. // | |
  1450. // | |
  1451. // | |
  1452. // | |
  1453. // +----------------------+
  1454. // 200,200
  1455. //
  1456. // Note that this does not restart the comparisons.
  1457. //
  1458. g_baBounds[iExist].Coord.bottom = pCand->top - 1;
  1459. break;
  1460. case OL_ENCLOSES:
  1461. //
  1462. // The existing encloses the candidate.
  1463. //
  1464. // 100,100
  1465. // +----------------------+
  1466. // | Exist |
  1467. // | |
  1468. // | 130,130 |
  1469. // | +------------+ |
  1470. // | | | |
  1471. // | | | |
  1472. // | | Cand | |
  1473. // | | | |
  1474. // | | | |
  1475. // | +------------+ |
  1476. // | 170,170 |
  1477. // | |
  1478. // +----------------------+
  1479. // 200,200
  1480. //
  1481. // Just discard the candidate by exiting.
  1482. //
  1483. //
  1484. //
  1485. // Return FALSE indicating that the rectangle is
  1486. // already catered for by the existing bounds
  1487. //
  1488. rc= FALSE;
  1489. DC_QUIT;
  1490. break;
  1491. case OL_PART_ENCLOSES_XMIN:
  1492. //
  1493. // The existing partially encloses the candidate - but
  1494. // not on the left.
  1495. //
  1496. // 100,100
  1497. // +----------------------+
  1498. // | Exist |
  1499. // 70,130 | |
  1500. // +-----+---------------+ |
  1501. // | | | |
  1502. // | | Cand | |
  1503. // | | | |
  1504. // +-----+---------------+ |
  1505. // | 170,170 |
  1506. // | |
  1507. // +----------------------+
  1508. // 200,200
  1509. //
  1510. // Adjust the candidate rectangle to be the non-
  1511. // overlapped portion.
  1512. //
  1513. // 100,100
  1514. // +----------------------+
  1515. // 70,130 | |
  1516. // +----+| |
  1517. // | || |
  1518. // | C || |
  1519. // | a || |
  1520. // | n || Exist |
  1521. // | d || |
  1522. // | || |
  1523. // +----+| |
  1524. // 99,170| |
  1525. // | |
  1526. // +----------------------+
  1527. // 200,200
  1528. //
  1529. // Because this affects the candidate, restart the
  1530. // comparisons to check for overlaps between the
  1531. // adjusted candidate and other existing rectangles.
  1532. //
  1533. //
  1534. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1535. fResetRects = TRUE;
  1536. break;
  1537. case OL_PART_ENCLOSES_XMAX:
  1538. //
  1539. // The existing partially encloses the candidate - but
  1540. // not on the right.
  1541. //
  1542. // 100,100
  1543. // +----------------------+
  1544. // | Exist |
  1545. // | |
  1546. // | 130,130 |
  1547. // | +-----------------+---+
  1548. // | | | |
  1549. // | | | |
  1550. // | | Cand | |
  1551. // | | | |
  1552. // | +-----------------+---+
  1553. // | | 220,170
  1554. // | |
  1555. // +----------------------+
  1556. // 200,200
  1557. //
  1558. // Adjust the candidate rectangle to be the non-
  1559. // overlapped portion.
  1560. //
  1561. // 100,100
  1562. // +----------------------+
  1563. // | |201,130
  1564. // | |+--+
  1565. // | || |
  1566. // | ||C |
  1567. // | Exist ||a |
  1568. // | ||n |
  1569. // | ||d |
  1570. // | || |
  1571. // | |+--+
  1572. // | | 220,170
  1573. // +----------------------+
  1574. // 200,200
  1575. //
  1576. // Because this affects the candidate, restart the
  1577. // comparisons to check for overlaps between the
  1578. // adjusted candidate and other existing rectangles.
  1579. //
  1580. //
  1581. pCand->left = g_baBounds[iExist].Coord.right + 1;
  1582. fResetRects = TRUE;
  1583. break;
  1584. case OL_PART_ENCLOSES_YMIN:
  1585. //
  1586. // The existing partially encloses the candidate - but
  1587. // not on the top.
  1588. //
  1589. // 70,130
  1590. // +---------+
  1591. // | |
  1592. // | |
  1593. // 100,100 | |
  1594. // +-----+---------+------+
  1595. // | | | |
  1596. // | | | |
  1597. // | | Cand | |
  1598. // | | | |
  1599. // | | | |
  1600. // | +---------+ |
  1601. // | 170,170 |
  1602. // | |
  1603. // | Exist |
  1604. // +----------------------+
  1605. // 200,200
  1606. //
  1607. // Adjust the candidate rectangle to be the non-
  1608. // overlapped portion.
  1609. //
  1610. //
  1611. // 70,130
  1612. // +---------+
  1613. // | |
  1614. // | Cand |
  1615. // | |
  1616. // 100,100 +---------+170,99
  1617. // +----------------------+
  1618. // | |
  1619. // | |
  1620. // | |
  1621. // | |
  1622. // | Exist |
  1623. // | |
  1624. // | |
  1625. // | |
  1626. // +----------------------+
  1627. // 200,200
  1628. //
  1629. // Because this affects the candidate, restart the
  1630. // comparisons to check for overlaps between the
  1631. // adjusted candidate and other existing rectangles.
  1632. //
  1633. //
  1634. pCand->bottom = g_baBounds[iExist].Coord.top - 1;
  1635. fResetRects = TRUE;
  1636. break;
  1637. case OL_PART_ENCLOSES_YMAX:
  1638. //
  1639. // The existing partially encloses the candidate - but
  1640. // not on the bottom.
  1641. //
  1642. // 100,100
  1643. // +----------------------+
  1644. // | Exist |
  1645. // | |
  1646. // | 130,130 |
  1647. // | +--------+ |
  1648. // | | | |
  1649. // | | | |
  1650. // | | Cand | |
  1651. // | | | |
  1652. // | | | |
  1653. // | | | |
  1654. // +-----+--------+-------+
  1655. // | | 200,200
  1656. // | |
  1657. // | |
  1658. // +--------+170,230
  1659. //
  1660. // Adjust the candidate rectangle to be the non-
  1661. // overlapped portion.
  1662. //
  1663. //
  1664. // 100,100
  1665. // +----------------------+
  1666. // | |
  1667. // | |
  1668. // | |
  1669. // | |
  1670. // | |
  1671. // | Exist |
  1672. // | |
  1673. // | |
  1674. // | |
  1675. // | |
  1676. // +----------------------+
  1677. // 130,201+---------+ 200,200
  1678. // | |
  1679. // | Cand |
  1680. // | |
  1681. // +---------+170,230
  1682. //
  1683. // Because this affects the candidate, restart the
  1684. // comparisons to check for overlaps between the
  1685. // adjusted candidate and other existing rectangles.
  1686. //
  1687. //
  1688. pCand->top = g_baBounds[iExist].Coord.bottom + 1;
  1689. fResetRects = TRUE;
  1690. break;
  1691. case OL_SPLIT_X:
  1692. //
  1693. // The existing overlaps the candicate, but neither can
  1694. // be merged or adjusted.
  1695. //
  1696. // 100,100
  1697. // +--------+
  1698. // | |
  1699. // 70,130 | Exist |
  1700. // +-----+--------+------+
  1701. // | | | |
  1702. // | | | |
  1703. // | Cand| | |
  1704. // | | | |
  1705. // | | | |
  1706. // +-----+--------+------+180,160
  1707. // | |
  1708. // | |
  1709. // +--------+150,200
  1710. //
  1711. // Need to split candidate into left and right halves.
  1712. //
  1713. // Only do a split if there is spare room in the list -
  1714. // because both the split rectangles may need to be
  1715. // added to the list.
  1716. //
  1717. // If there is spare room, split the candidate into a
  1718. // smaller candidate on the left and a new rectangle on
  1719. // the right. Call this routine recursively to handle
  1720. // the new rectangle.
  1721. //
  1722. // 100,100
  1723. // +--------+
  1724. // | |
  1725. // 70,130 | |151,130
  1726. // +----+| |+-----+
  1727. // | || || |
  1728. // | || || |
  1729. // |Cand|| Exist || New |
  1730. // | || || |
  1731. // | || || |
  1732. // +----+| |+-----+
  1733. // 99,160| | 180,160
  1734. // | |
  1735. // +--------+150,200
  1736. //
  1737. // After the recursion, because the candidate has
  1738. // changed, restart the comparisons to check for
  1739. // overlaps between the adjusted candidate and other
  1740. // existing rectangles.
  1741. //
  1742. //
  1743. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1744. (level < ADDR_RECURSE_LIMIT))
  1745. {
  1746. rectNew.left = g_baBounds[iExist].Coord.right + 1;
  1747. rectNew.right = pCand->right;
  1748. rectNew.top = pCand->top;
  1749. rectNew.bottom = pCand->bottom;
  1750. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1751. TRACE_OUT(( "*** RECURSION ***"));
  1752. BAAddRect(&rectNew, level);
  1753. TRACE_OUT(( "*** RETURN ***"));
  1754. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1755. {
  1756. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1757. DC_QUIT;
  1758. }
  1759. fResetRects = TRUE;
  1760. }
  1761. break;
  1762. case OL_SPLIT_Y:
  1763. //
  1764. // The existing overlaps the candicate, but neither can
  1765. // be merged or adjusted.
  1766. //
  1767. // 100,100
  1768. // +--------+
  1769. // | |
  1770. // 70,130 | Cand |
  1771. // +-----+--------+------+
  1772. // | | | |
  1773. // | | | |
  1774. // |Exist| | |
  1775. // | | | |
  1776. // | | | |
  1777. // +-----+--------+------+180,160
  1778. // | |
  1779. // | |
  1780. // +--------+150,200
  1781. //
  1782. // Need to split candidate into top and bottom halves.
  1783. //
  1784. // Only do a split if there is spare room in the list -
  1785. // because both the split rectangles may need to be
  1786. // added to the list.
  1787. //
  1788. // If there is spare room, split the candidate into a
  1789. // smaller candidate on the top and a new rectangle on
  1790. // the bottom. Call this routine recursively to handle
  1791. // the new rectangle.
  1792. //
  1793. // 100,100
  1794. // +--------+
  1795. // | Cand |
  1796. // 70,130 +--------+150,129
  1797. // +---------------------+
  1798. // | |
  1799. // | |
  1800. // | |
  1801. // | |
  1802. // | |
  1803. // +---------------------+180,160
  1804. // 100,161+--------+
  1805. // | New |
  1806. // +--------+150,200
  1807. //
  1808. // After the recursion, because the candidate has
  1809. // changed, restart the comparisons to check for
  1810. // overlaps between the adjusted candidate and other
  1811. // existing rectangles.
  1812. //
  1813. //
  1814. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1815. (level < ADDR_RECURSE_LIMIT))
  1816. {
  1817. rectNew.left = pCand->left;
  1818. rectNew.right = pCand->right;
  1819. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  1820. rectNew.bottom = pCand->bottom;
  1821. pCand->bottom = g_baBounds[iExist].Coord.top - 1;
  1822. TRACE_OUT(( "*** RECURSION ***"));
  1823. BAAddRect(&rectNew, level);
  1824. TRACE_OUT(( "*** RETURN ***"));
  1825. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1826. {
  1827. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1828. DC_QUIT;
  1829. }
  1830. fResetRects = TRUE;
  1831. }
  1832. break;
  1833. case OL_SPLIT_XMIN_YMIN:
  1834. //
  1835. // The existing overlaps the candicate, but neither can
  1836. // be merged or adjusted.
  1837. //
  1838. // 100,100
  1839. // +---------------+
  1840. // | Cand |
  1841. // | |
  1842. // | |
  1843. // | 150,150 |
  1844. // | +-------+-----+
  1845. // | | | |
  1846. // | | | |
  1847. // | | | |
  1848. // | | | |
  1849. // | | | |
  1850. // +-------+-------+ |
  1851. // | 200,200 |
  1852. // | |
  1853. // | Exist |
  1854. // | |
  1855. // +-------------+
  1856. // 250,250
  1857. //
  1858. // Need to split candidate into top and left pieces.
  1859. //
  1860. // Only do a split if there is spare room in the list -
  1861. // because both the split rectangles may need to be
  1862. // added to the list.
  1863. //
  1864. // If there is spare room, split the candidate into a
  1865. // smaller candidate on the left and a new rectangle on
  1866. // the top. Call this routine recursively to handle
  1867. // the new rectangle.
  1868. //
  1869. // 100,100 151,100
  1870. // +-------+-------+
  1871. // | | |
  1872. // | | New |
  1873. // | | |
  1874. // | | |200,149
  1875. // | +-------+-----+
  1876. // | Cand |150,150 |
  1877. // | | |
  1878. // | | |
  1879. // | | |
  1880. // | | Exist |
  1881. // +-------+ |
  1882. // 150,200| |
  1883. // | |
  1884. // | |
  1885. // | |
  1886. // +-------------+
  1887. // 250,250
  1888. //
  1889. // After the recursion, because the candidate has
  1890. // changed, restart the comparisons to check for
  1891. // overlaps between the adjusted candidate and other
  1892. // existing rectangles.
  1893. //
  1894. //
  1895. if ( g_baRectsUsed < BA_NUM_RECTS )
  1896. {
  1897. rectNew.left = g_baBounds[iExist].Coord.left;
  1898. rectNew.right = pCand->right;
  1899. rectNew.top = pCand->top;
  1900. rectNew.bottom = g_baBounds[iExist].Coord.top - 1;
  1901. pCand->right = g_baBounds[iExist].Coord.left - 1;
  1902. TRACE_OUT(( "*** RECURSION ***"));
  1903. BAAddRect(&rectNew, level);
  1904. TRACE_OUT(( "*** RETURN ***"));
  1905. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1906. {
  1907. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1908. DC_QUIT;
  1909. }
  1910. fResetRects = TRUE;
  1911. }
  1912. break;
  1913. case OL_SPLIT_XMAX_YMIN:
  1914. //
  1915. // The existing overlaps the candicate, but neither can
  1916. // be merged or adjusted.
  1917. //
  1918. // 150,100
  1919. // +---------------+
  1920. // | |
  1921. // | Cand |
  1922. // 100,150 | |
  1923. // +------+--------+ |
  1924. // | | | |
  1925. // | | | |
  1926. // | | | |
  1927. // | | | |
  1928. // | | | |
  1929. // | | | |
  1930. // | +--------+------+
  1931. // | | 250,200
  1932. // | Exist |
  1933. // | |
  1934. // +---------------+
  1935. // 200,250
  1936. //
  1937. // Need to split candidate into top and right pieces.
  1938. //
  1939. // Only do a split if there is spare room in the list -
  1940. // because both the split rectangles may need to be
  1941. // added to the list.
  1942. //
  1943. // If there is spare room, split the candidate into a
  1944. // smaller candidate on the right and a new rectangle
  1945. // on the top. Call this routine recursively to handle
  1946. // the new rectangle.
  1947. //
  1948. // 150,100 201,100
  1949. // +--------+------+
  1950. // | New | |
  1951. // | | |
  1952. // 100,150 | 200,149| |
  1953. // +------+--------+ |
  1954. // | | Cand |
  1955. // | | |
  1956. // | | |
  1957. // | | |
  1958. // | Exist | |
  1959. // | | |
  1960. // | +------+
  1961. // | | 250,200
  1962. // | |
  1963. // | |
  1964. // +---------------+
  1965. // 200,250
  1966. //
  1967. // After the recursion, because the candidate has
  1968. // changed, restart the comparisons to check for
  1969. // overlaps between the adjusted candidate and other
  1970. // existing rectangles.
  1971. //
  1972. //
  1973. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  1974. (level < ADDR_RECURSE_LIMIT))
  1975. {
  1976. rectNew.left = pCand->left;
  1977. rectNew.right = g_baBounds[iExist].Coord.right;
  1978. rectNew.top = pCand->top;
  1979. rectNew.bottom = g_baBounds[iExist].Coord.top - 1;
  1980. pCand->left = g_baBounds[iExist].Coord.right + 1;
  1981. TRACE_OUT(( "*** RECURSION ***"));
  1982. BAAddRect(&rectNew, level);
  1983. TRACE_OUT(( "*** RETURN ***"));
  1984. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  1985. {
  1986. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  1987. DC_QUIT;
  1988. }
  1989. fResetRects = TRUE;
  1990. }
  1991. break;
  1992. case OL_SPLIT_XMIN_YMAX:
  1993. //
  1994. // The existing overlaps the candicate, but neither can
  1995. // be merged or adjusted.
  1996. //
  1997. // 150,100
  1998. // +---------------+
  1999. // | |
  2000. // | Exist |
  2001. // 100,150 | |
  2002. // +------+--------+ |
  2003. // | | | |
  2004. // | | | |
  2005. // | | | |
  2006. // | | | |
  2007. // | | | |
  2008. // | | | |
  2009. // | +--------+------+
  2010. // | | 250,200
  2011. // | Cand |
  2012. // | |
  2013. // +---------------+
  2014. // 200,250
  2015. //
  2016. // Need to split candidate into left and bottom pieces.
  2017. //
  2018. // Only do a split if there is spare room in the list -
  2019. // because both the split rectangles may need to be
  2020. // added to the list.
  2021. //
  2022. // If there is spare room, split the candidate into a
  2023. // smaller candidate on the left and a new rectangle on
  2024. // the bottom. Call this routine recursively to handle
  2025. // the new rectangle.
  2026. //
  2027. // 150,100
  2028. // +---------------+
  2029. // | |
  2030. // | |
  2031. // 100,150 | |
  2032. // +------+ |
  2033. // | | |
  2034. // | | |
  2035. // | | |
  2036. // | | |
  2037. // | Cand | |
  2038. // | | |
  2039. // | +--------+------+
  2040. // | |151,200 | 250,200
  2041. // | | |
  2042. // | | New |
  2043. // +------+--------+
  2044. // 149,250 200,250
  2045. //
  2046. // After the recursion, because the candidate has
  2047. // changed, restart the comparisons to check for
  2048. // overlaps between the adjusted candidate and other
  2049. // existing rectangles.
  2050. //
  2051. //
  2052. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  2053. (level < ADDR_RECURSE_LIMIT))
  2054. {
  2055. rectNew.left = g_baBounds[iExist].Coord.left;
  2056. rectNew.right = pCand->right;
  2057. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  2058. rectNew.bottom = pCand->bottom;
  2059. pCand->right = g_baBounds[iExist].Coord.left - 1;
  2060. TRACE_OUT(( "*** RECURSION ***"));
  2061. BAAddRect(&rectNew, level);
  2062. TRACE_OUT(( "*** RETURN ***"));
  2063. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  2064. {
  2065. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  2066. DC_QUIT;
  2067. }
  2068. fResetRects = TRUE;
  2069. }
  2070. break;
  2071. case OL_SPLIT_XMAX_YMAX:
  2072. //
  2073. // The existing overlaps the candicate, but neither can
  2074. // be merged or adjusted.
  2075. //
  2076. // 100,100
  2077. // +---------------+
  2078. // | Exist |
  2079. // | |
  2080. // | |
  2081. // | 150,150 |
  2082. // | +-------+-----+
  2083. // | | | |
  2084. // | | | |
  2085. // | | | |
  2086. // | | | |
  2087. // | | | |
  2088. // +-------+-------+ |
  2089. // | 200,200 |
  2090. // | |
  2091. // | Cand |
  2092. // | |
  2093. // +-------------+
  2094. // 250,250
  2095. //
  2096. // Need to split candidate into bottom and right pieces.
  2097. //
  2098. // Only do a split if there is spare room in the list -
  2099. // because both the split rectangles may need to be
  2100. // added to the list.
  2101. //
  2102. // If there is spare room, split the candidate into a
  2103. // smaller candidate on the right and a new rectangle
  2104. // on the bottom. Call this routine recursively to
  2105. // handle the new rectangle.
  2106. //
  2107. // 100,100
  2108. // +---------------+
  2109. // | |
  2110. // | |
  2111. // | |
  2112. // | |201,150
  2113. // | Exist +-----+
  2114. // | | |
  2115. // | | |
  2116. // | | |
  2117. // | |Cand |
  2118. // | 200,200| |
  2119. // +-------+-------+ |
  2120. // 150,201| | |
  2121. // | | |
  2122. // | New | |
  2123. // | | |
  2124. // +-------+-----+
  2125. // 200,250 250,250
  2126. //
  2127. // After the recursion, because the candidate has
  2128. // changed, restart the comparisons to check for
  2129. // overlaps between the adjusted candidate and other
  2130. // existing rectangles.
  2131. //
  2132. //
  2133. if ((g_baRectsUsed < BA_NUM_RECTS) &&
  2134. (level < ADDR_RECURSE_LIMIT))
  2135. {
  2136. rectNew.left = pCand->left;
  2137. rectNew.right = g_baBounds[iExist].Coord.right;
  2138. rectNew.top = g_baBounds[iExist].Coord.bottom + 1;
  2139. rectNew.bottom = pCand->bottom;
  2140. pCand->left = g_baBounds[iExist].Coord.right + 1;
  2141. TRACE_OUT(( "*** RECURSION ***"));
  2142. BAAddRect(&rectNew, level);
  2143. TRACE_OUT(( "*** RETURN ***"));
  2144. if (!fRectToAdd && !g_baBounds[iLastMerge].InUse)
  2145. {
  2146. TRACE_OUT(( "FINISHED - %d", iLastMerge));
  2147. DC_QUIT;
  2148. }
  2149. fResetRects = TRUE;
  2150. }
  2151. break;
  2152. default:
  2153. //
  2154. // This should not happen.
  2155. //
  2156. ERROR_OUT(( "Unrecognised overlap case-%d",OverlapType));
  2157. break;
  2158. }
  2159. iExist = (fResetRects) ? g_baFirstRect :
  2160. g_baBounds[iExist].iNext;
  2161. }
  2162. //
  2163. // Arriving here means that no overlap was found between the
  2164. // candidate and the existing rectangles.
  2165. //
  2166. // - If the candidate is the original rectangle, add it to the
  2167. // list.
  2168. // - If the candidate is an existing rectangle, it is already in
  2169. // the list.
  2170. //
  2171. if ( fRectToAdd )
  2172. {
  2173. BAAddRectList(pCand);
  2174. }
  2175. //
  2176. // The compare and add processing above is allowed to add a
  2177. // rectangle to the list when there are already BA_NUM_RECTS
  2178. // (eg. when doing a split or when there is no overlap at all with
  2179. // the existing rectangles) - and there is an extra slot for that
  2180. // purpose.
  2181. //
  2182. // If we now have more than BA_NUM_RECTS rectangles, do a
  2183. // forced merge, so that the next call to this routine has a spare
  2184. // slot.
  2185. //
  2186. //
  2187. fRectMerged = ( g_baRectsUsed > BA_NUM_RECTS );
  2188. if ( fRectMerged )
  2189. {
  2190. //
  2191. // Start looking for merged rectangles.
  2192. //
  2193. // For each rectangle in the list, compare it with the others,
  2194. // and Determine cost of merging.
  2195. //
  2196. // We want to merge the two rectangles with the minimum
  2197. // area difference, ie that will produce a merged
  2198. // rectangle that covers the least superfluous screen
  2199. // area.
  2200. //
  2201. // Note that we calculate the areas of the rectangles here
  2202. // (rather than on the fly as they are created/ manipulated in
  2203. // the loop), as the statistics show that forced merges occur
  2204. // very much less frequently than non-forced manipulations (ie
  2205. // splits, adds etc.
  2206. //
  2207. //
  2208. bestMergeIncrease = 0x7FFFFFFF;
  2209. for ( iExist = g_baFirstRect;
  2210. iExist != BA_INVALID_RECT_INDEX;
  2211. iExist = g_baBounds[iExist].iNext )
  2212. {
  2213. g_baBounds[iExist].Area =
  2214. COM_SizeOfRectInclusive(&g_baBounds[iExist].Coord);
  2215. }
  2216. #ifdef _DEBUG
  2217. iBestMerge1 = BA_INVALID_RECT_INDEX;
  2218. iBestMerge2 = BA_INVALID_RECT_INDEX;
  2219. #endif
  2220. for ( iExist = g_baFirstRect;
  2221. iExist != BA_INVALID_RECT_INDEX;
  2222. iExist = g_baBounds[iExist].iNext )
  2223. {
  2224. for ( iTmp = g_baBounds[iExist].iNext;
  2225. iTmp != BA_INVALID_RECT_INDEX;
  2226. iTmp = g_baBounds[iTmp].iNext )
  2227. {
  2228. rectNew.left = min( g_baBounds[iExist].Coord.left,
  2229. g_baBounds[iTmp].Coord.left );
  2230. rectNew.top = min( g_baBounds[iExist].Coord.top,
  2231. g_baBounds[iTmp].Coord.top );
  2232. rectNew.right = max( g_baBounds[iExist].Coord.right,
  2233. g_baBounds[iTmp].Coord.right );
  2234. rectNew.bottom = max( g_baBounds[iExist].Coord.bottom,
  2235. g_baBounds[iTmp].Coord.bottom );
  2236. mergeIncrease = COM_SizeOfRectInclusive(&rectNew) -
  2237. g_baBounds[iExist].Area - g_baBounds[iTmp].Area;
  2238. if (bestMergeIncrease > mergeIncrease)
  2239. {
  2240. iBestMerge1 = iExist;
  2241. iBestMerge2 = iTmp;
  2242. bestMergeIncrease = mergeIncrease;
  2243. }
  2244. }
  2245. }
  2246. ASSERT(iBestMerge1 != BA_INVALID_RECT_INDEX);
  2247. ASSERT(iBestMerge2 != BA_INVALID_RECT_INDEX);
  2248. //
  2249. // Now do the merge.
  2250. //
  2251. // We recalculate the size of the merged rectangle here -
  2252. // alternatively we could remember the size of the best so far
  2253. // in the loop above. The trade off is between calculating
  2254. // twice or copying at least once but probably more than once
  2255. // as we find successively better merges.
  2256. //
  2257. TRACE_OUT(("BestMerge1 %d, {%d,%d,%d,%d}", iBestMerge1,
  2258. g_baBounds[iBestMerge1].Coord.left,
  2259. g_baBounds[iBestMerge1].Coord.top,
  2260. g_baBounds[iBestMerge1].Coord.right,
  2261. g_baBounds[iBestMerge1].Coord.bottom ));
  2262. TRACE_OUT(("BestMerge2 %d, {%d,%d,%d,%d}", iBestMerge2,
  2263. g_baBounds[iBestMerge2].Coord.left,
  2264. g_baBounds[iBestMerge2].Coord.top,
  2265. g_baBounds[iBestMerge2].Coord.right,
  2266. g_baBounds[iBestMerge2].Coord.bottom ));
  2267. g_baBounds[iBestMerge1].Coord.left =
  2268. min( g_baBounds[iBestMerge1].Coord.left,
  2269. g_baBounds[iBestMerge2].Coord.left );
  2270. g_baBounds[iBestMerge1].Coord.top =
  2271. min( g_baBounds[iBestMerge1].Coord.top,
  2272. g_baBounds[iBestMerge2].Coord.top );
  2273. g_baBounds[iBestMerge1].Coord.right =
  2274. max( g_baBounds[iBestMerge1].Coord.right,
  2275. g_baBounds[iBestMerge2].Coord.right );
  2276. g_baBounds[iBestMerge1].Coord.bottom =
  2277. max( g_baBounds[iBestMerge1].Coord.bottom,
  2278. g_baBounds[iBestMerge2].Coord.bottom );
  2279. //
  2280. // Remove the second best merge.
  2281. //
  2282. BA_RemoveRectList(&(g_baBounds[iBestMerge2].Coord));
  2283. //
  2284. // The best merged rectangle becomes the candidate, and we fall
  2285. // back to the head of the comparison loop to start again.
  2286. //
  2287. pCand = &(g_baBounds[iBestMerge1].Coord);
  2288. iLastMerge = iBestMerge1;
  2289. fRectToAdd = FALSE;
  2290. }
  2291. } while ( fRectMerged );
  2292. DC_EXIT_POINT:
  2293. DebugExitBOOL(BAAddRect, rc);
  2294. return(rc);
  2295. }