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.

1292 lines
31 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dcrgn.cxx
  3. *
  4. * Non inline DC Region object routines
  5. *
  6. * Created: 02-Jul-1990 12:36:30
  7. * Author: Donald Sidoroff [donalds]
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. RECTL rclEmpty = {POS_INFINITY,POS_INFINITY,NEG_INFINITY,NEG_INFINITY};
  13. #if DBG
  14. ULONG dbgrgn = 0;
  15. HDC gflhdc = 0;
  16. VOID DisplayRegion(
  17. PREGION prgn,
  18. PCHAR s
  19. )
  20. {
  21. DbgPrint("DisplayRegion %s = 0x%p\n",s,prgn);
  22. if (prgn)
  23. {
  24. DbgPrint("Region bounding rect = (%li,%li) to (%li,%li)\n",
  25. prgn->rcl.left,
  26. prgn->rcl.top,
  27. prgn->rcl.right,
  28. prgn->rcl.bottom
  29. );
  30. }
  31. }
  32. #endif
  33. /******************************Public*Routine******************************\
  34. * DC::bCompute()
  35. *
  36. * Compute the current Rao region. The Rao region is the ANDed version of
  37. * all the regions. Since the only region that must exist is the Vis region
  38. * we allow this to be the Rao without actually computing it. (Refer to the
  39. * prgnEffRao() method) This is only done if no other regions are defined.
  40. * This is a nifty accelerator.
  41. *
  42. * WARNING: This routine should only be called while the device is locked.
  43. * calling at any other time doesn't make sense, since our vis region may
  44. * change asynchronously.
  45. *
  46. * History:
  47. *
  48. * 11-Jul-1995 -by- Mark Enstrom [marke]
  49. *
  50. * Don't always delete and re-allocate rao region
  51. *
  52. * 07-Mar-1992 -by- Donald Sidoroff [donalds]
  53. * Complete rewrite
  54. *
  55. * 09-Jul-1990 -by- Donald Sidoroff [donalds]
  56. * Wrote it.
  57. \**************************************************************************/
  58. BOOL DC::bCompute()
  59. {
  60. ASSERTDEVLOCK(this);
  61. RGNLOG rl(prgnVis(),"DC::bCompute",(ULONG_PTR)prgnRao());
  62. ASSERTGDI(prgnVis() != NULL,"DC::bCompute - prgnVis == NULL\n");
  63. BOOL bRes = FALSE;
  64. if (!(prgnVis() == NULL))
  65. {
  66. bRes = TRUE;
  67. //
  68. // quick check to see if there is just the vis rgn. Better to pay
  69. // the cost of the check twice in the rare case to speed up the check
  70. // for the common case
  71. //
  72. RGNOBJ roVis(prgnVis());
  73. if (((ULONG_PTR)prgnClip() | (ULONG_PTR)prgnMeta() | (ULONG_PTR)prgnAPI()) == 0)
  74. {
  75. //
  76. // get rid of RAO now since it won't be needed
  77. //
  78. if (prgnRao() != NULL)
  79. {
  80. RGNOBJ roRao(prgnRao());
  81. roRao.bDeleteRGNOBJ();
  82. prgnRao(NULL);
  83. }
  84. //
  85. // set erclClip to the bounding rcl
  86. //
  87. roVis.vGetSubRect(&(erclClip()));
  88. //
  89. // Mark as clean
  90. //
  91. fsClr(DC_DIRTY_RAO);
  92. }
  93. else
  94. {
  95. PREGION aprgn[3];
  96. int cRgn = 0;
  97. //
  98. // Load the regions into the buffer
  99. //
  100. if ((aprgn[cRgn] = prgnClip()) != NULL)
  101. {
  102. cRgn++;
  103. }
  104. if ((aprgn[cRgn] = prgnMeta()) != NULL)
  105. {
  106. cRgn++;
  107. }
  108. if ((aprgn[cRgn] = prgnAPI()) != NULL)
  109. {
  110. cRgn++;
  111. }
  112. RGNOBJ roRao(prgnRao());
  113. if (roRao.prgn == NULL)
  114. {
  115. //
  116. // need to create RAO
  117. //
  118. RGNMEMOBJ rmoRao;
  119. if (rmoRao.bValid())
  120. {
  121. roRao.prgn = rmoRao.prgn;
  122. }
  123. }
  124. if (!roRao.bValid())
  125. {
  126. bRes = FALSE;
  127. }
  128. else if (cRgn == 1)
  129. {
  130. RGNOBJ ro(aprgn[0]);
  131. if (!roRao.bCopy(ro))
  132. {
  133. bRes = FALSE;
  134. }
  135. }
  136. else if (cRgn == 2)
  137. {
  138. RGNOBJ roA(aprgn[0]);
  139. RGNOBJ roB(aprgn[1]);
  140. if (roRao.iCombine(roA, roB, RGN_AND) == ERROR)
  141. {
  142. bRes = FALSE;
  143. }
  144. }
  145. else
  146. {
  147. RGNMEMOBJTMP rmo;
  148. RGNOBJ roA(aprgn[0]);
  149. RGNOBJ roB(aprgn[1]);
  150. RGNOBJ roC(aprgn[2]);
  151. if (!rmo.bValid() ||
  152. (rmo.iCombine(roA, roB, RGN_AND) == ERROR) ||
  153. (roRao.iCombine(rmo, roC, RGN_AND) == ERROR))
  154. {
  155. bRes = FALSE;
  156. }
  157. }
  158. if (bRes)
  159. {
  160. roRao.vStamp();
  161. //
  162. // We first have to offset the new Rao,
  163. //
  164. if (roRao.bOffset((PPOINTL) prclWindow()))
  165. {
  166. //
  167. // If the Vis is a rectangle and bounds the Rao, we are done
  168. //
  169. if (roVis.bRectl() && roVis.bContain(roRao))
  170. {
  171. prgnRao(roRao.prgnGet());
  172. roRao.vGetSubRect(&(erclClip()));
  173. fsClr(DC_DIRTY_RAO);
  174. }
  175. else
  176. {
  177. //
  178. // Sigh, once again we find ourselves looking for a place to do a merge.
  179. //
  180. RGNMEMOBJTMP rmo;
  181. if (!rmo.bValid() ||
  182. (rmo.iCombine(roVis, roRao, RGN_AND) == ERROR) ||
  183. !roRao.bCopy(rmo))
  184. {
  185. bRes = FALSE;
  186. }
  187. else
  188. {
  189. prgnRao(roRao.prgnGet());
  190. roRao.vGetSubRect(&(erclClip()));
  191. fsClr(DC_DIRTY_RAO);
  192. }
  193. }
  194. }
  195. else
  196. {
  197. bRes = FALSE;
  198. }
  199. }
  200. if (!bRes)
  201. {
  202. WARNING("DC::bCompute failed");
  203. //
  204. // RAO creation failed at some point, bswap may have
  205. // already deleted the old RAO rgn, so the DC pointer
  206. // must be set to NULL
  207. //
  208. prgnRao(NULL);
  209. if (roRao.bValid())
  210. {
  211. //
  212. // if the RAO still exists,
  213. // then delete it.
  214. //
  215. roRao.bDeleteRGNOBJ();
  216. }
  217. }
  218. }
  219. //
  220. // update user-mode vis region bounding rectangle if dirty
  221. //
  222. vUpdate_VisRect(prgnVis());
  223. }
  224. return(bRes);
  225. }
  226. /******************************Public*Routine******************************\
  227. * LONG DC::iCombine(prcl, iMode)
  228. *
  229. * Combine the clip region with the rectangle by the mode
  230. *
  231. * History:
  232. * 09-Jul-1990 -by- Donald Sidoroff [donalds]
  233. * Wrote it.
  234. \**************************************************************************/
  235. LONG DC::iCombine(
  236. RECTL *prcl,
  237. LONG iMode)
  238. {
  239. PREGION prgn = prgnClip();
  240. LONG iTmp;
  241. if (!VALID_SCRPRC(prcl))
  242. {
  243. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  244. return(ERROR);
  245. }
  246. RGNMEMOBJ rmoRcl;
  247. if (!rmoRcl.bValid())
  248. return(ERROR);
  249. rmoRcl.vSet(prcl);
  250. vReleaseRao();
  251. if (prgn != NULL)
  252. {
  253. RGNMEMOBJ rmo;
  254. if (!rmo.bValid())
  255. {
  256. iTmp = ERROR;
  257. }
  258. else
  259. {
  260. RGNOBJ ro(prgn);
  261. iTmp = rmo.iCombine(ro, rmoRcl, iMode);
  262. if (iTmp != ERROR)
  263. {
  264. rmo.vSelect((HDC)hGet());
  265. prgnClip(rmo.prgnGet());
  266. #if DBG
  267. if ((dbgrgn) && (gflhdc == hGet()))
  268. {
  269. DbgPrint("iCombine: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  270. }
  271. #endif
  272. // If nobody is using the old clip region, delete it.
  273. ro.vUnselect();
  274. if (ro.cGet_cRefs() == 0)
  275. ro.bDeleteRGNOBJ();
  276. }
  277. else
  278. {
  279. rmo.bDeleteRGNOBJ();
  280. }
  281. }
  282. rmoRcl.bDeleteRGNOBJ();
  283. }
  284. else if (iMode == RGN_AND)
  285. {
  286. rmoRcl.vSelect((HDC)hGet());
  287. prgnClip(rmoRcl.prgnGet());
  288. #if DBG
  289. if ((dbgrgn) && (gflhdc == hGet()))
  290. {
  291. DbgPrint("iCombine: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  292. }
  293. #endif
  294. iTmp = SIMPLEREGION;
  295. }
  296. else
  297. {
  298. RGNMEMOBJ rmo2;
  299. RGNMEMOBJTMP rmo3;
  300. SIZEL sizl;
  301. if (!rmo2.bValid())
  302. {
  303. iTmp = ERROR;
  304. }
  305. else if (!rmo3.bValid())
  306. {
  307. rmo2.bDeleteRGNOBJ();
  308. iTmp = ERROR;
  309. }
  310. else
  311. {
  312. vGet_sizlWindow(&sizl);
  313. ERECTL ercl(0, 0, sizl.cx, sizl.cy);
  314. //
  315. // Bug #310012: Under multimon, the rectangle isn't necessarily
  316. // based at 0,0.
  317. //
  318. PDEVOBJ pdo(hdev());
  319. ASSERTGDI(pdo.bValid(), "Invalid pdev\n");
  320. {
  321. DEVLOCKOBJ dl(pdo);
  322. if (pdo.bMetaDriver() && bHasSurface() && pSurface()->bPDEVSurface())
  323. {
  324. ercl += *pdo.pptlOrigin();
  325. }
  326. }
  327. // Clip Rgn is maintained in the DC coordinate space;
  328. // so, the window on physical device surface needs to be
  329. // converted into DC coordinates. DC Window shown in PDEV
  330. // coordinates.
  331. //
  332. // (0,0) sizl.cx
  333. // +-----------------------+
  334. // | |
  335. // | PDEV Surface |
  336. // (eptlOrigin) | |
  337. // +----------+-----------+ |
  338. // | | | | sizl.cy
  339. // | DC Window | |
  340. // | (erclWindow) | |
  341. // | | | |
  342. // +----------+-----------+ |
  343. // | |
  344. // +-----------------------+
  345. //
  346. // With the eptlOrigin adjustment the clip will be positioned
  347. // as shown below.
  348. //
  349. // (0,0) (-eptlOrigin)
  350. // +----------+-----------+-----------+
  351. // | | | |
  352. // | DC Window | |
  353. // | (erclWindow-eptlOrigin) |
  354. // | | | |
  355. // +----------+-----------+ |
  356. // | |
  357. // | Default Clip Region |
  358. // | |
  359. // | |
  360. // +-----------------------+
  361. //
  362. // Note: erclWindow-epltOrigin-eptlOrigin may give us more
  363. // narrow clip region, but using dclevel.sizl-eptlOrigin
  364. // will get the job done since we get that more narrow
  365. // area when combined with prgnVis.
  366. ercl -= eptlOrigin();
  367. if (!ercl.bEmpty() && ercl.bWrapped())
  368. {
  369. iTmp = ERROR;
  370. }
  371. if (iTmp != ERROR)
  372. {
  373. rmo3.vSet((PRECTL) &ercl);
  374. iTmp = rmo2.iCombine(rmo3, rmoRcl, iMode);
  375. if (iTmp != ERROR)
  376. {
  377. rmo2.vSelect((HDC)hGet());
  378. prgnClip(rmo2.prgnGet());
  379. #if DBG
  380. if ((dbgrgn) && (gflhdc == hGet()))
  381. {
  382. DbgPrint("iCombine: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  383. }
  384. #endif
  385. }
  386. else
  387. {
  388. rmo2.bDeleteRGNOBJ();
  389. }
  390. }
  391. rmoRcl.bDeleteRGNOBJ();
  392. }
  393. }
  394. return(iTmp);
  395. }
  396. /******************************Public*Routine******************************\
  397. * LONG DC::iCombine(pexo, prcl, iMode)
  398. *
  399. * Combine the clip region a possibly transformed rectangle by the given mode
  400. *
  401. * History:
  402. * 28-Apr-1992 -by- Donald Sidoroff [donalds]
  403. * Wrote it.
  404. \**************************************************************************/
  405. LONG DC::iCombine(
  406. EXFORMOBJ *pexo,
  407. RECTL *prcl,
  408. LONG iMode)
  409. {
  410. POINTL aptl[4];
  411. aptl[0].x = prcl->left;
  412. aptl[0].y = prcl->top;
  413. aptl[1].x = prcl->right;
  414. aptl[1].y = prcl->top;
  415. aptl[2].x = prcl->right;
  416. aptl[2].y = prcl->bottom;
  417. aptl[3].x = prcl->left;
  418. aptl[3].y = prcl->bottom;
  419. // Create a path, and draw the parallelogram.
  420. PATHMEMOBJ pmo;
  421. if (!pmo.bValid())
  422. {
  423. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  424. return(ERROR);
  425. }
  426. if (!pmo.bMoveTo(pexo, &aptl[0]))
  427. return(ERROR);
  428. if (!pmo.bPolyLineTo(pexo, &aptl[1], 3))
  429. return(ERROR);
  430. if (!pmo.bCloseFigure())
  431. return(ERROR);
  432. // Now, convert it back into a region.
  433. RGNMEMOBJ rmoPlg(pmo, ALTERNATE);
  434. if (!rmoPlg.bValid())
  435. {
  436. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  437. return(ERROR);
  438. }
  439. // Merge it into the current clipping region.
  440. REGION *prgn = prgnClip();
  441. LONG iTmp = ERROR;
  442. vReleaseRao();
  443. if (prgn != NULL)
  444. {
  445. RGNMEMOBJ rmo;
  446. if (rmo.bValid())
  447. {
  448. RGNOBJ ro(prgn);
  449. iTmp = rmo.iCombine(ro, rmoPlg, iMode);
  450. if (iTmp != ERROR)
  451. {
  452. rmo.vSelect((HDC)hGet());
  453. prgnClip(rmo.prgnGet());
  454. #if DBG
  455. if ((dbgrgn) && (gflhdc == hGet()))
  456. {
  457. DbgPrint("iCombine: hdc = 0x%lx, new region = 0x%lx\n",hHmgr,prgnClip());
  458. }
  459. #endif
  460. // If nobody is using the old clip region, delete it.
  461. ro.vUnselect();
  462. if (ro.cGet_cRefs() == 0)
  463. ro.bDeleteRGNOBJ();
  464. }
  465. else
  466. {
  467. rmo.bDeleteRGNOBJ();
  468. }
  469. }
  470. rmoPlg.bDeleteRGNOBJ();
  471. }
  472. else if (iMode == RGN_AND)
  473. {
  474. rmoPlg.vSelect((HDC)hGet());
  475. prgnClip(rmoPlg.prgnGet());
  476. #if DBG
  477. if ((dbgrgn) && (gflhdc == hGet()))
  478. {
  479. DbgPrint("iCombine: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  480. }
  481. #endif
  482. iTmp = rmoPlg.iComplexity();
  483. }
  484. else
  485. {
  486. RGNMEMOBJ rmo2;
  487. SIZEL sizl;
  488. if (rmo2.bValid())
  489. {
  490. RGNMEMOBJTMP rmo3;
  491. if (!rmo3.bValid())
  492. {
  493. rmo2.bDeleteRGNOBJ();
  494. }
  495. else
  496. {
  497. vGet_sizlWindow(&sizl);
  498. ERECTL ercl(0, 0, sizl.cx, sizl.cy);
  499. //
  500. // Bug #310012: Under multimon, the rectangle isn't necessarily
  501. // based at 0,0.
  502. //
  503. PDEVOBJ pdo(hdev());
  504. ASSERTGDI(pdo.bValid(), "Invalid pdev\n");
  505. {
  506. DEVLOCKOBJ dl(pdo);
  507. if (pdo.bMetaDriver() && bHasSurface() && pSurface()->bPDEVSurface())
  508. {
  509. ercl += *pdo.pptlOrigin();
  510. }
  511. }
  512. // Place Clip Region in DC Coordinates
  513. // See comments in DC::iCombine(lprcl, iMode) above.
  514. ercl -= eptlOrigin();
  515. rmo3.vSet((PRECTL) &ercl);
  516. iTmp = rmo2.iCombine(rmo3, rmoPlg, iMode);
  517. if (iTmp == ERROR)
  518. {
  519. rmo2.bDeleteRGNOBJ();
  520. }
  521. else
  522. {
  523. rmo2.vSelect((HDC)hGet());
  524. prgnClip(rmo2.prgnGet());
  525. #if DBG
  526. if ((dbgrgn) && (gflhdc == hGet()))
  527. {
  528. DbgPrint("iCombine: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  529. }
  530. #endif
  531. }
  532. }
  533. }
  534. rmoPlg.bDeleteRGNOBJ();
  535. }
  536. return(iTmp);
  537. }
  538. /******************************Public*Routine******************************\
  539. * BOOL DC::bReset()
  540. *
  541. * Reset regions associated with the DC
  542. *
  543. * History:
  544. * 05-Jul-1990 -by- Donald Sidoroff [donalds]
  545. * Wrote it.
  546. \**************************************************************************/
  547. BOOL DC::bReset()
  548. {
  549. #if DBG
  550. if (dbgrgn)
  551. {
  552. DbgPrint("DC::bReset()\n");
  553. }
  554. #endif
  555. REGION *prgn;
  556. if ((prgn = dclevel.prgnMeta) != NULL)
  557. {
  558. RGNOBJ roMeta(prgn);
  559. roMeta.vUnselect();
  560. if (roMeta.cGet_cRefs() == 0)
  561. roMeta.bDeleteRGNOBJ();
  562. dclevel.prgnMeta = NULL;
  563. vReleaseRao();
  564. }
  565. if ((prgn = dclevel.prgnClip) != NULL)
  566. {
  567. RGNOBJ roClip(prgn);
  568. roClip.vUnselect();
  569. if (roClip.cGet_cRefs() == 0)
  570. roClip.bDeleteRGNOBJ();
  571. dclevel.prgnClip = NULL;
  572. vReleaseRao();
  573. }
  574. return(TRUE);
  575. }
  576. /******************************Public*Routine******************************\
  577. * BOOL bSaveRegion(dco, cLevel)
  578. *
  579. * Save the DC's regions
  580. *
  581. * History:
  582. * 07-May-1991 -by- Donald Sidoroff [donalds]
  583. * Wrote it.
  584. \**************************************************************************/
  585. BOOL bSaveRegion(DCOBJ& dco, LONG cLevel)
  586. {
  587. if (cLevel == 1)
  588. {
  589. RECTL rcl;
  590. SIZEL sizl;
  591. dco.pdc->vGet_sizl(&sizl);
  592. rcl.left = 0;
  593. rcl.bottom = 0;
  594. rcl.right = sizl.cx;
  595. rcl.top = sizl.cy;
  596. {
  597. RGNMEMOBJ rmo;
  598. if (!rmo.bValid())
  599. return(FALSE);
  600. //
  601. // Bug #310012: Under multimon, the rectangle isn't necessarily
  602. // based at 0,0.
  603. //
  604. PDEVOBJ pdo(dco.hdev());
  605. ASSERTGDI(pdo.bValid(), "Invalid pdev\n");
  606. {
  607. DEVLOCKOBJ dl(pdo);
  608. if (pdo.bMetaDriver() && dco.bHasSurface() && dco.pSurface()->bPDEVSurface())
  609. {
  610. ((ERECTL) rcl) += *pdo.pptlOrigin();
  611. }
  612. }
  613. rmo.vSet(&rcl);
  614. dco.pdc->prgnVis(rmo.prgnGet());
  615. }
  616. return(TRUE);
  617. }
  618. DCOBJ dcoSaved(dco.hdcSave());
  619. if (!dcoSaved.bLocked())
  620. return(FALSE);
  621. PREGION prgn;
  622. if ((prgn = dcoSaved.pdc->prgnMeta()) != NULL)
  623. {
  624. RGNOBJ roMeta(prgn);
  625. roMeta.vSelect(dco.hdc());
  626. }
  627. if ((prgn = dcoSaved.pdc->prgnClip()) != NULL)
  628. {
  629. RGNOBJ roClip(prgn);
  630. roClip.vSelect(dco.hdc());
  631. }
  632. return(TRUE);
  633. }
  634. /******************************Public*Routine******************************\
  635. * VOID vRestoreRegion(dco, cLevel)
  636. *
  637. * Restore the DC's regions
  638. *
  639. * History:
  640. * 08-May-1991 -by- Donald Sidoroff [donalds]
  641. * Wrote it.
  642. \**************************************************************************/
  643. VOID vRestoreRegion(DCOBJ& dco, LONG cLevel)
  644. {
  645. DONTUSE(cLevel); // needed to keep save/restore calls happy
  646. PREGION prgn;
  647. if ((prgn = dco.pdc->prgnMeta()) != NULL)
  648. {
  649. RGNOBJ roMeta(prgn);
  650. roMeta.vUnselect();
  651. if (roMeta.cGet_cRefs() == 0)
  652. roMeta.bDeleteRGNOBJ();
  653. }
  654. if ((prgn = dco.pdc->prgnClip()) != NULL)
  655. {
  656. RGNOBJ roClip(prgn);
  657. roClip.vUnselect();
  658. if (roClip.cGet_cRefs() == 0)
  659. roClip.bDeleteRGNOBJ();
  660. }
  661. }
  662. /******************************Public*Routine******************************\
  663. * int DC::iSelect(hrgn, iMode)
  664. *
  665. * Select the region into the DC as the current clip region
  666. *
  667. * History:
  668. * 17-Sep-1991 -by- Donald Sidoroff [donalds]
  669. * Made DC::iSelect for SelectObject/SelectClipRgn compatibility.
  670. *
  671. * 02-Sep-1990 -by- Donald Sidoroff [donalds]
  672. * Wrote it.
  673. \**************************************************************************/
  674. int DC::iSelect(HRGN hrgn, int iMode)
  675. {
  676. int iRet;
  677. if (hrgn != (HRGN)0)
  678. {
  679. RGNOBJAPI ro(hrgn,TRUE);
  680. if (ro.bValid())
  681. iRet = iSelect(ro.prgnGet(),iMode);
  682. else
  683. iRet = RGN_ERROR;
  684. }
  685. else
  686. {
  687. if (iMode == RGN_COPY)
  688. iRet = iSelect((PREGION)NULL,iMode);
  689. else
  690. iRet = RGN_ERROR;
  691. }
  692. return(iRet);
  693. }
  694. /******************************Member*Function*****************************\
  695. *
  696. * History:
  697. * 23-Oct-1993 -by- Eric Kutter [erick]
  698. * Wrote it.
  699. \**************************************************************************/
  700. int DC::iSelect(PREGION prgn, int iMode)
  701. {
  702. PREGION prgnOld = prgnClip();
  703. PREGION prgnNew = NULL;
  704. int iRet = RGN_ERROR;
  705. if ((iMode == RGN_COPY) ||
  706. ((iMode == RGN_AND) && (prgn != NULL) && (prgnOld == NULL)))
  707. {
  708. //
  709. // Select in a region?
  710. //
  711. if (prgn != NULL)
  712. {
  713. RGNOBJ ro(prgn);
  714. RGNOBJ roClip(prgnOld);
  715. //
  716. // There was no old region so create a new region and
  717. // copy the input region to it, or the old region can't
  718. // be modified due to other references.
  719. //
  720. if ((prgnOld == NULL) || (roClip.cGet_cRefs() != 1))
  721. {
  722. RGNMEMOBJ rmo(ro.sizeRgn());
  723. if (rmo.bValid())
  724. {
  725. rmo.vCopy(ro);
  726. rmo.vSelect((HDC)hGet());
  727. prgnNew = rmo.prgnGet();
  728. iRet = (int) rmo.iComplexity();
  729. //
  730. // select new region in and release RAO
  731. //
  732. prgnClip(prgnNew);
  733. vReleaseRao();
  734. //
  735. // If there was an old clip region, it must be
  736. // unreferenced.
  737. //
  738. if (prgnOld != NULL)
  739. {
  740. roClip.vUnselect();
  741. if (roClip.cGet_cRefs() == 0)
  742. {
  743. roClip.bDeleteRGNOBJ();
  744. }
  745. }
  746. }
  747. }
  748. else
  749. {
  750. //
  751. // select in a new region, there already was an old one so
  752. // bCopy the new to the old
  753. //
  754. if (roClip.bCopy(ro))
  755. {
  756. //
  757. // bCopy might change prgn
  758. //
  759. prgnNew = roClip.prgnGet();
  760. iRet = (int) roClip.iComplexity();
  761. //
  762. // set new region pointer and release RAO
  763. //
  764. prgnClip(prgnNew);
  765. vReleaseRao();
  766. }
  767. }
  768. }
  769. else
  770. {
  771. iRet = SIMPLEREGION;
  772. //
  773. // new clip region is NULL, delete old if it exists
  774. //
  775. if (prgnOld != NULL)
  776. {
  777. RGNOBJ roClip(prgnOld);
  778. roClip.vUnselect();
  779. if (roClip.cGet_cRefs() == 0)
  780. {
  781. roClip.bDeleteRGNOBJ();
  782. }
  783. prgnClip(NULL);
  784. vReleaseRao();
  785. }
  786. }
  787. }
  788. else
  789. {
  790. //
  791. // We didn't simply select the new region.
  792. //
  793. RGNOBJ ro(prgn);
  794. RGNMEMOBJ rmo;
  795. if (rmo.bValid())
  796. {
  797. if (prgnOld != NULL)
  798. {
  799. RGNOBJ roClip(prgnOld);
  800. if ((iRet = (int) rmo.iCombine(roClip,ro,iMode)) != RGN_ERROR)
  801. {
  802. rmo.vSelect((HDC)hGet());
  803. prgnNew = rmo.prgnGet();
  804. prgnClip(prgnNew);
  805. #if DBG
  806. if (dbgrgn)
  807. {
  808. DbgPrint("iSelect: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  809. }
  810. #endif
  811. vReleaseRao();
  812. roClip.vUnselect();
  813. if (roClip.cGet_cRefs() == 0)
  814. {
  815. roClip.bDeleteRGNOBJ();
  816. }
  817. }
  818. }
  819. else
  820. {
  821. //
  822. // Since no clip region exists, make a dummy the size of the surface
  823. //
  824. RGNMEMOBJTMP rmo2;
  825. SIZEL sizl;
  826. if (rmo2.bValid())
  827. {
  828. vGet_sizlWindow(&sizl);
  829. ERECTL ercl(0, 0, sizl.cx, sizl.cy);
  830. //
  831. // Bug #310012: Under multimon, the rectangle isn't necessarily
  832. // based at 0,0.
  833. //
  834. PDEVOBJ pdo(hdev());
  835. ASSERTGDI(pdo.bValid(), "Invalid pdev\n");
  836. {
  837. DEVLOCKOBJ dl(pdo);
  838. if (pdo.bMetaDriver() && bHasSurface() && pSurface()->bPDEVSurface())
  839. {
  840. ercl += *pdo.pptlOrigin();
  841. }
  842. }
  843. // Place Clip Region in DC Coordinates
  844. // See comments in DC::iCombine(lprcl, iMode) above.
  845. ercl -= eptlOrigin();
  846. rmo2.vSet((PRECTL) &ercl);
  847. iRet = (int) rmo.iCombine(rmo2,ro,iMode);
  848. if (iRet != RGN_ERROR)
  849. {
  850. rmo.vSelect((HDC)hGet());
  851. prgnNew = rmo.prgnGet();
  852. prgnClip(prgnNew);
  853. #if DBG
  854. if (dbgrgn)
  855. {
  856. DbgPrint("iSelect: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  857. }
  858. #endif
  859. vReleaseRao();
  860. }
  861. }
  862. }
  863. if (iRet == RGN_ERROR)
  864. {
  865. rmo.bDeleteRGNOBJ();
  866. }
  867. }
  868. }
  869. return(iRet);
  870. }
  871. /******************************Public*Routine******************************\
  872. * int DC::iSetMetaRgn()
  873. *
  874. * Select the region into the DC as the current meta region
  875. *
  876. * History:
  877. * 01-Nov-1991 19:13:33 -by- Donald Sidoroff [donalds]
  878. * Wrote it.
  879. *
  880. * 25-Nov-1992 -by- Eric Kutter [erick]
  881. * rewrote
  882. \**************************************************************************/
  883. int DC::iSetMetaRgn()
  884. {
  885. #if DBG
  886. if (dbgrgn)
  887. {
  888. DbgPrint("DC::iSetMetaRgn()\n");
  889. }
  890. #endif
  891. int iRet = RGN_ERROR;
  892. if (prgnMeta() == (PREGION)0)
  893. {
  894. if (prgnClip() == NULL)
  895. return(SIMPLEREGION);
  896. RGNOBJ ro(prgnClip());
  897. iRet = (int) ro.iComplexity();
  898. // NOTE: Since we're just copying the handle, the reference counts should
  899. // remain the same.
  900. prgnMeta(prgnClip());
  901. prgnClip(NULL);
  902. #if DBG
  903. if (dbgrgn)
  904. {
  905. DbgPrint("iSetMetaRgn: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  906. }
  907. #endif
  908. return(iRet);
  909. }
  910. else
  911. {
  912. RGNOBJ roMeta(prgnMeta());
  913. // if we only have a meta rgn, just return that.
  914. if (prgnClip() == NULL)
  915. return(roMeta.iComplexity());
  916. // need the merge the two into a new region
  917. RGNOBJ roClip(prgnClip());
  918. RGNMEMOBJ rmo;
  919. if (!rmo.bValid())
  920. return(iRet);
  921. // combine the regions
  922. iRet = (int) rmo.iCombine(roMeta,roClip,RGN_AND);
  923. if (iRet != RGN_ERROR)
  924. {
  925. rmo.vSelect((HDC)hGet());
  926. // delete the old meta rgn
  927. prgnMeta(rmo.prgnGet());
  928. roMeta.vUnselect();
  929. if (roMeta.cGet_cRefs() == 0)
  930. roMeta.bDeleteRGNOBJ();
  931. // delete the old clip rgn
  932. prgnClip(NULL);
  933. #if DBG
  934. if (dbgrgn)
  935. {
  936. DbgPrint("iSetMetaRgn: hdc = 0x%p, new region = 0x%p\n",hHmgr,prgnClip());
  937. }
  938. #endif
  939. roClip.vUnselect();
  940. if (roClip.cGet_cRefs() == 0)
  941. roClip.bDeleteRGNOBJ();
  942. vReleaseRao();
  943. }
  944. else
  945. rmo.bDeleteRGNOBJ();
  946. }
  947. return(iRet);
  948. }
  949. /******************************Public*Routine******************************\
  950. * VOID DC::vReleaseVis()
  951. *
  952. * Release the current VisRgn
  953. *
  954. * History:
  955. * 06-Mar-1992 -by- Donald Sidoroff [donalds]
  956. * Wrote it.
  957. \**************************************************************************/
  958. VOID DC::vReleaseVis()
  959. {
  960. #if DBG
  961. if ((dbgrgn) && (gflhdc == hGet()))
  962. {
  963. DbgPrint("DC::vReleaseVis\n");
  964. }
  965. #endif
  966. fsSet(DC_DIRTY_RAO);
  967. PENTRY_FROM_POBJ(this)->Flags |= HMGR_ENTRY_INVALID_VIS;
  968. erclClip(&rclEmpty);
  969. ASSERTGDI(prgnVis() != NULL,"DC::vReleaseVis - prgnVis == NULL\n");
  970. RGNLOG rl((HRGN)prgnVis(),0,"DC::vReleaseVis");
  971. prgnVis()->vDeleteREGION();
  972. prgnVis(prgnDefault);
  973. }
  974. /******************************Public*Routine******************************\
  975. * VOID DC::vReleaseRao()
  976. *
  977. * Release the current RaoRgn
  978. *
  979. * History:
  980. * 06-Mar-1992 -by- Donald Sidoroff [donalds]
  981. * Wrote it.
  982. \**************************************************************************/
  983. VOID DC::vReleaseRao()
  984. {
  985. #if DBG
  986. if ((dbgrgn) && (gflhdc == hGet()))
  987. {
  988. DbgPrint("DC::vReleaseRao\n");
  989. }
  990. #endif
  991. fsSet(DC_DIRTY_RAO);
  992. PENTRY_FROM_POBJ(this)->Flags |= HMGR_ENTRY_INVALID_VIS;
  993. erclClip(&rclEmpty);
  994. RGNLOG rl(prgnRao(),"DC::vReleaseRao");
  995. }