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.

3089 lines
94 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: brushobj.cxx
  3. *
  4. * Support for brmemobj.hxx and brushobj.hxx.
  5. *
  6. * Created: 06-Dec-1990 12:02:24
  7. * Author: Walt Moore [waltm]
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. extern "C" BOOL bInitBRUSHOBJ();
  13. extern "C" BOOL bInitBrush(int iBrush, COLORREF cr,
  14. DWORD dwHS, PULONG_PTR pdw, BOOL bEnableDither);
  15. #pragma alloc_text(INIT, bInitBRUSHOBJ)
  16. #pragma alloc_text(INIT, bInitBrush)
  17. // Global pointer to the last RBRUSH freed, if any (for one-deep caching).
  18. PRBRUSH gpCachedDbrush = NULL;
  19. PRBRUSH gpCachedEngbrush = NULL;
  20. #define MAX_STOCKBRUSHES 4*1024
  21. LONG gStockBrushFree = MAX_STOCKBRUSHES;
  22. //#define DBG_STOCKBRUSHES 1
  23. #if DBG_STOCKBRUSHES
  24. #define STOCKWARNING DbgPrint
  25. #define STOCKINFO DbgPrint
  26. #else
  27. #define STOCKWARNING
  28. #define STOCKINFO
  29. #endif
  30. extern "C" HFASTMUTEX ghfmMemory;
  31. #if DBG
  32. LONG bo_inits, bo_realize, bo_notdirty, bo_cachehit;
  33. LONG bo_missnotcached, bo_missfg, bo_missbg, bo_misspaltime, bo_misssurftime;
  34. #endif
  35. /****************************Global*Public*Data******************************\
  36. *
  37. * These are the 5 global brushes and 3 global pens maintained by GDI.
  38. * These are retrieved through GetStockObject.
  39. *
  40. * History:
  41. * 20-May-1991 -by- Patrick Haluptzok patrickh
  42. * Wrote it.
  43. \**************************************************************************/
  44. HBRUSH ghbrText;
  45. HBRUSH ghbrBackground;
  46. HBRUSH ghbrGrayPattern;
  47. PBRUSH gpbrText;
  48. PBRUSH gpbrNull;
  49. PBRUSH gpbrBackground;
  50. PPEN gpPenNull;
  51. HBRUSH ghbrDCBrush;
  52. PBRUSH gpbrDCBrush;
  53. HBRUSH ghbrDCPen;
  54. PBRUSH gpbrDCPen;
  55. // Uniqueness so a logical handle can be reused without having it look like
  56. // the same brush as before. We don't really care where this starts.
  57. ULONG BRUSH::_ulGlobalBrushUnique = 0;
  58. ULONG gCacheHandleEntries[GDI_CACHED_HADNLE_TYPES] = {
  59. CACHE_BRUSH_ENTRIES ,
  60. CACHE_PEN_ENTRIES ,
  61. CACHE_REGION_ENTRIES,
  62. CACHE_LFONT_ENTRIES
  63. };
  64. ULONG gCacheHandleOffsets[GDI_CACHED_HADNLE_TYPES] = {
  65. 0,
  66. CACHE_BRUSH_ENTRIES,
  67. (
  68. CACHE_BRUSH_ENTRIES +
  69. CACHE_PEN_ENTRIES
  70. ),
  71. (
  72. CACHE_BRUSH_ENTRIES +
  73. CACHE_PEN_ENTRIES +
  74. CACHE_PEN_ENTRIES
  75. )
  76. };
  77. /******************************Public*Routine******************************\
  78. * bPEBCacheHandle
  79. *
  80. * Try to place the object(handle) in a free list on the PEB. The objects
  81. * are removed from this list in user mode.
  82. *
  83. * Arguments:
  84. *
  85. * Handle - handle to cache
  86. * HandleType - type of handle to attempt cache
  87. * pBrushattr - pointer to user-mode object
  88. *
  89. * Return Value:
  90. *
  91. * TRUE if handle is cached, FALSE otherwise
  92. *
  93. * History:
  94. *
  95. * 30-Jan-1996 -by- Mark Enstrom [marke]
  96. *
  97. \**************************************************************************/
  98. BOOL
  99. bPEBCacheHandle(
  100. HANDLE Handle,
  101. HANDLECACHETYPE HandleType,
  102. POBJECTATTR pObjectattr,
  103. PENTRY pentry
  104. )
  105. {
  106. BOOL bRet = FALSE;
  107. PBRUSHATTR pBrushattr = (PBRUSHATTR)pObjectattr;
  108. PW32PROCESS pw32Process = W32GetCurrentProcess();
  109. PPEB Peb;
  110. #if !defined(_GDIPLUS_)
  111. ASSERTGDI(((HandleType == BrushHandle) || (HandleType == PenHandle) ||
  112. (HandleType == RegionHandle) ||(HandleType == LFontHandle)
  113. ),"hGetPEBHandle: illegal handle type");
  114. Peb = PsGetProcessPeb(pw32Process->Process);
  115. if (Peb != NULL)
  116. {
  117. PGDIHANDLECACHE pCache = (PGDIHANDLECACHE)(&Peb->GdiHandleBuffer[0]);
  118. BOOL bStatus;
  119. //
  120. // Lock Handle cache on PEB
  121. //
  122. LOCK_HANDLE_CACHE(pCache,PsGetCurrentThread(),bStatus);
  123. if (bStatus)
  124. {
  125. //
  126. // are any free slots still availablle
  127. //
  128. if (pCache->ulNumHandles[HandleType] < gCacheHandleEntries[HandleType])
  129. {
  130. ULONG Index = gCacheHandleOffsets[HandleType];
  131. PHANDLE pHandle,pMaxHandle;
  132. //
  133. // calculate handle offset in PEB array
  134. //
  135. pHandle = &(pCache->Handle[Index]);
  136. pMaxHandle = pHandle + gCacheHandleEntries[HandleType];
  137. //
  138. // search array for a free entry
  139. //
  140. while (pHandle != pMaxHandle)
  141. {
  142. if (*pHandle == NULL)
  143. {
  144. //
  145. // for increased robust behavior, increment handle unique
  146. //
  147. pentry->FullUnique += UNIQUE_INCREMENT;
  148. Handle = (HOBJ)MAKE_HMGR_HANDLE((ULONG)(ULONG_PTR)Handle & INDEX_MASK, pentry->FullUnique);
  149. pentry->einfo.pobj->hHmgr = Handle;
  150. //
  151. // store handle in cache and inc stored count
  152. //
  153. *pHandle = Handle;
  154. pCache->ulNumHandles[HandleType]++;
  155. bRet = TRUE;
  156. //
  157. // clear to be deleted and select flags,
  158. // set cached flag
  159. //
  160. pBrushattr->AttrFlags &= ~(ATTR_TO_BE_DELETED | ATTR_CANT_SELECT);
  161. pBrushattr->AttrFlags |= ATTR_CACHED;
  162. break;
  163. }
  164. pHandle++;
  165. }
  166. ASSERTGDI(bRet,"bPEBCacheHandle: count indicates free handle, but none free\n");
  167. }
  168. UNLOCK_HANDLE_CACHE(pCache);
  169. }
  170. }
  171. #endif
  172. return(bRet);
  173. }
  174. /******************************Public*Routine******************************\
  175. * BRUSHMEMOBJ::pbrAllocBrush(bPen)
  176. *
  177. * Base constructor for brush memory object. This constructor is to be
  178. * called by the various public brush constructors only.
  179. *
  180. * History:
  181. * 29-Oct-1992 -by- Michael Abrash [mikeab]
  182. * changed to allocate but not get a handle or lock (so the brush can be fully
  183. * set up before the handle exists, exposing the data to the outside world).
  184. *
  185. * Wed 19-Jun-1991 -by- Patrick Haluptzok [patrickh]
  186. * 0 out the brush.
  187. *
  188. * Thu 06-Dec-1990 12:02:41 -by- Walt Moore [waltm]
  189. * Wrote it.
  190. \**************************************************************************/
  191. PBRUSH BRUSHMEMOBJ::pbrAllocBrush(BOOL bPen)
  192. {
  193. PBRUSH pbrush;
  194. bKeep = FALSE;
  195. // Allocate a new brush or pen
  196. //
  197. // Note: if anyone decides to try turning off zeroinit for performance,
  198. // make sure to initialize the pen's psytle and cstyle to zero. Of
  199. // course, other dependencies may creep in, so do this very very very
  200. // carefully (if you even dare!).
  201. if ((pbrush = (PBRUSH)ALLOCOBJ(bPen ? sizeof(PEN) : sizeof(BRUSH),
  202. BRUSH_TYPE, TRUE)) != NULL)
  203. {
  204. pbrush->pBrushattr(&pbrush->_Brushattr);
  205. pbrush->pIcmDIBList(NULL); // no ICM translated DIBs
  206. pbrush->iUsage(0);
  207. // Set up as initially not caching any realization
  208. pbrush->vSetNotCached(); // no one's trying to cache a realization
  209. // in this logical brush yet
  210. pbrush->crFore((COLORREF)BO_NOTCACHED);
  211. // no cached realization yet (no need to
  212. // worry about crFore not being set when
  213. // someone tries to check for caching,
  214. // because we don't have a handle yet, and
  215. // we'll lock when we do get the handle,
  216. // forcing writes to flush)
  217. pbrush->ulBrushUnique(pbrush->ulGlobalBrushUnique());
  218. // set the uniqueness so the are-you-
  219. // really-dirty check in vInitBrush will
  220. // know this is not the brush in the DC
  221. }
  222. return(pbrush);
  223. }
  224. /******************************Public*Routine******************************\
  225. * BRUSHMEMOBJ::BRUSHMEMOBJ
  226. *
  227. * Create a pattern brush or a DIB brush.
  228. *
  229. * History:
  230. * 29-Oct-1992 -by- Michael Abrash [mikeab]
  231. * changed to get handle only after fully initialized
  232. *
  233. * 14-May-1991 -by- Patrick Haluptzok patrickh
  234. * Wrote it.
  235. \**************************************************************************/
  236. BRUSHMEMOBJ::BRUSHMEMOBJ(HBITMAP hbmClone, HBITMAP hbmClient,BOOL bMono,
  237. FLONG flDIB, FLONG flType, BOOL bPen)
  238. {
  239. if (flDIB == DIB_PAL_COLORS)
  240. {
  241. flType |= BR_IS_DIBPALCOLORS;
  242. }
  243. else if (flDIB == DIB_PAL_INDICES)
  244. {
  245. flType |= BR_IS_DIBPALINDICES;
  246. }
  247. PBRUSH pbrush;
  248. if ((pbp.pbr = pbrush = pbrAllocBrush(bPen)) != NULL)
  249. {
  250. pbrush->crColor(0);
  251. pbrush->ulStyle(HS_PAT);
  252. pbrush->hbmPattern(hbmClone);
  253. pbrush->hbmClient(hbmClient);
  254. pbrush->AttrFlags(0);
  255. pbrush->flAttrs(flType);
  256. if (bMono)
  257. {
  258. pbrush->flAttrs(pbrush->flAttrs() |
  259. (BR_NEED_BK_CLR | BR_NEED_FG_CLR | BR_IS_MONOCHROME));
  260. }
  261. // Now that everything is set up, create the handle and expose this logical
  262. // brush
  263. if (HmgInsertObject(pbrush, HMGR_ALLOC_ALT_LOCK, BRUSH_TYPE) == 0)
  264. {
  265. FREEOBJ(pbrush, BRUSH_TYPE);
  266. pbp.pbr = NULL;
  267. }
  268. }
  269. else
  270. {
  271. WARNING1("Brush allocation failed\n");
  272. }
  273. }
  274. /******************************Public*Routine******************************\
  275. * GreSetSolidBrush
  276. *
  277. * Chicago API to change the color of a solid color brush.
  278. *
  279. * History:
  280. * 19-Apr-1994 -by- Patrick Haluptzok patrickh
  281. * Made it a function that User can call too.
  282. *
  283. * 03-Dec-1993 -by- Eric Kutter [erick]
  284. * Wrote it - bReset.
  285. \**************************************************************************/
  286. BOOL GreSetSolidBrush(HBRUSH hbr, COLORREF clr)
  287. {
  288. return(GreSetSolidBrushInternal(hbr, clr, FALSE, TRUE));
  289. }
  290. BOOL GreSetSolidBrushInternal(
  291. HBRUSH hbr,
  292. COLORREF clr,
  293. BOOL bPen,
  294. BOOL bUserCalled
  295. )
  296. {
  297. BOOL bReturn = FALSE;
  298. BRUSHSELOBJ ebo(hbr);
  299. PBRUSH pbrush = ebo.pbrush();
  300. if (pbrush != NULL)
  301. {
  302. if ((pbrush->flAttrs() & BR_IS_SOLID) &&
  303. ((!pbrush->bIsGlobal()) || bUserCalled) &&
  304. ((!!pbrush->bIsPen()) == bPen))
  305. {
  306. #if DBG
  307. if (bPen)
  308. {
  309. ASSERTGDI(((PPEN) pbrush)->pstyle() == NULL ||
  310. (pbrush->flAttrs() & BR_IS_DEFAULTSTYLE),
  311. "GreSetSolidBrush - bad attrs\n");
  312. }
  313. #endif
  314. ASSERTGDI(pbrush->hbmPattern() == NULL,
  315. "ERROR how can solid have pat");
  316. PRBRUSH prbrush = (PRBRUSH) NULL;
  317. RBTYPE rbType;
  318. {
  319. //
  320. // Can't do the delete of the RBRUSH under MLOCK, takes too
  321. // long and it may try and grab it again.
  322. //
  323. MLOCKFAST mlo;
  324. //
  325. // User may call when the brush is selected in a DC, but
  326. // the client side should only ever call on a brush that's
  327. // not in use.
  328. //
  329. if ((pbrush->cShareLockGet() == 1) || bUserCalled)
  330. {
  331. bReturn = TRUE;
  332. pbrush->crColor(clr);
  333. HANDLELOCK HandleLock(PENTRY_FROM_POBJ(pbrush), FALSE);
  334. if (HandleLock.bValid())
  335. {
  336. if (pbrush->cShareLockGet() == 1)
  337. {
  338. //
  339. // Nobody is using it and we have the handle lock
  340. // so noone can select it in till we are done. So
  341. // clean out the old realization now.
  342. //
  343. if ((pbrush->crFore() != BO_NOTCACHED) &&
  344. !pbrush->bCachedIsSolid())
  345. {
  346. prbrush = (PRBRUSH) pbrush->ulRealization();
  347. rbType = pbrush->bIsEngine() ? RB_ENGINE
  348. : RB_DRIVER;
  349. }
  350. // Set up as initially not caching any realization
  351. pbrush->vSetNotCached();
  352. // no one's trying to cache a realization
  353. // in this logical brush yet
  354. pbrush->crFore((COLORREF)BO_NOTCACHED);
  355. // no cached realization yet (no need to
  356. // worry about crFore not being set when
  357. // someone tries to check for caching,
  358. // because we don't have a handle yet, and
  359. // we'll lock when we do get the handle,
  360. // forcing writes to flush)
  361. if (!bUserCalled)
  362. {
  363. //
  364. // If it's not User calling we are resetting the
  365. // attributes / type.
  366. //
  367. pbrush->ulStyle(HS_DITHEREDCLR);
  368. pbrush->flAttrs(BR_IS_SOLID | BR_DITHER_OK);
  369. }
  370. else
  371. {
  372. pbrush->vClearSolidRealization();
  373. }
  374. }
  375. else
  376. {
  377. //ASSERTGDI(bUserCalled,
  378. // "Client side is hosed, shouldn't "
  379. // "call this with it still selected");
  380. ASSERTGDI(pbrush->flAttrs() & BR_IS_SOLID,
  381. "ERROR not solid");
  382. ASSERTGDI(pbrush->ulStyle() == HS_DITHEREDCLR,
  383. "ERROR not HS_DI");
  384. //
  385. // Mark this brushes realization as dirty by setting
  386. // it's cache id's to invalid states. Note that if a
  387. // realization hasn't been cached yet this will cause
  388. // no problem either.
  389. //
  390. pbrush->crBack(0xFFFFFFFF);
  391. pbrush->ulPalTime(0xFFFFFFFF);
  392. pbrush->ulSurfTime(0xFFFFFFFF);
  393. //
  394. // This brush is being used other places, check for
  395. // any DC's that have this brush selected in and mark
  396. // their realizations dirty.
  397. //
  398. // Note there is the theoretical possibility that
  399. // somebody is realizing the brush while we are
  400. // marking them dirty and they won't pick up the new
  401. // color. We set the color first and set the
  402. // uniqueness last so that it is extremely unlikely
  403. // (maybe impossible) that someone gets a realization
  404. // that incorrectly thinks it has the proper
  405. // realization. This is fixable by protecting access
  406. // to the realization and cache fields but we aren't
  407. // going to do it for Daytona.
  408. //
  409. // Mark every DC in the system that has this brush
  410. // selected as a dirty brush.
  411. //
  412. HOBJ hobj = (HOBJ) 0;
  413. DC *pdc;
  414. while ((pdc = (DC *) HmgSafeNextObjt(hobj, DC_TYPE))
  415. != NULL)
  416. {
  417. if (pdc->peboFill()->pbrush() == pbrush)
  418. {
  419. pdc->flbrushAdd(DIRTY_FILL);
  420. }
  421. hobj = (HOBJ) pdc->hGet();
  422. }
  423. }
  424. HandleLock.vUnlock();
  425. }
  426. //
  427. // Set the uniqueness so the are-you-
  428. // really-dirty check in vInitBrush will
  429. // not think an old realization is still valid.
  430. //
  431. pbrush->ulBrushUnique(pbrush->ulGlobalBrushUnique());
  432. }
  433. else
  434. {
  435. WARNING1("Error, SetSolidBrush with cShare != 1");
  436. }
  437. }
  438. if (prbrush)
  439. {
  440. prbrush->vRemoveRef(rbType);
  441. }
  442. }
  443. #if DBG
  444. else
  445. {
  446. if (bPen)
  447. {
  448. WARNING1("bPen True\n");
  449. }
  450. if (pbrush->bIsPen())
  451. {
  452. WARNING1("bIsPen True\n");
  453. }
  454. if (bUserCalled)
  455. {
  456. WARNING1("bUserCalled\n");
  457. }
  458. if (pbrush->bIsGlobal())
  459. {
  460. WARNING1("bIsGlobal\n");
  461. }
  462. if (pbrush->flAttrs() & BR_IS_SOLID)
  463. {
  464. WARNING1("BR_IS_SOLID is set\n");
  465. }
  466. WARNING1("GreSetSolidBrush not passed a solid color brush\n");
  467. }
  468. #endif
  469. }
  470. #if DBG
  471. else
  472. {
  473. WARNING1("GreSetSolidBrush failed to lock down brush\n");
  474. }
  475. #endif
  476. return(bReturn);
  477. }
  478. /******************************Public*Routine******************************\
  479. * GreSetSolidBrushLight:
  480. *
  481. * Private version of GreSetSolidBrush, user can't call
  482. *
  483. * Arguments:
  484. *
  485. * pbrush - pointer to log brush
  486. * clr - new color
  487. * bPen - Brush is a pen
  488. *
  489. * Return Value:
  490. *
  491. * Status
  492. *
  493. * History:
  494. *
  495. * 2-Nov-1995 -by- Mark Enstrom [marke]
  496. *
  497. \**************************************************************************/
  498. BOOL
  499. GreSetSolidBrushLight(
  500. PBRUSH pbrush,
  501. COLORREF clr,
  502. BOOL bPen
  503. )
  504. {
  505. BOOL bReturn = FALSE;
  506. if (pbrush != NULL)
  507. {
  508. if (
  509. (pbrush->flAttrs() & BR_IS_SOLID) &&
  510. (!pbrush->bIsGlobal())
  511. )
  512. {
  513. //
  514. // make sure bPen flag matches brush type
  515. //
  516. if ((bPen != 0) == (pbrush->bIsPen() != 0))
  517. {
  518. #if DBG
  519. if (bPen)
  520. {
  521. ASSERTGDI(((PPEN) pbrush)->pstyle() == NULL ||
  522. (pbrush->flAttrs() & BR_IS_DEFAULTSTYLE),
  523. "GreSetSolidBrushLight - illegal PEN attrs\n");
  524. }
  525. #endif
  526. ASSERTGDI(pbrush->hbmPattern() == NULL,
  527. "ERROR how can solid have pat");
  528. PRBRUSH prbrush = (PRBRUSH) NULL;
  529. RBTYPE rbType;
  530. {
  531. //
  532. // Grab the handle lock to stabize the lock counts.
  533. // Do not attempt to free the realized brush under
  534. // this lock; it may take to long.
  535. //
  536. ASSERTGDI(pbrush->hGet(),
  537. "ERROR brush obj has no handle\n");
  538. HANDLELOCK HandleLock(PENTRY_FROM_POBJ(pbrush),FALSE);
  539. if (HandleLock.bValid())
  540. {
  541. if (pbrush->cShareLockGet() == 1)
  542. {
  543. bReturn = TRUE;
  544. pbrush->crColor(clr);
  545. //
  546. // Nobody is using it and we have the HANDLELOCK
  547. // so noone can select it in till we are done. So
  548. // clean out the old realization now.
  549. //
  550. if ((pbrush->crFore() != BO_NOTCACHED) &&
  551. !pbrush->bCachedIsSolid())
  552. {
  553. prbrush = (PRBRUSH) pbrush->ulRealization();
  554. rbType = pbrush->bIsEngine() ? RB_ENGINE
  555. : RB_DRIVER;
  556. }
  557. //
  558. // Set up as initially not caching any realization
  559. //
  560. pbrush->vSetNotCached();
  561. // no one's trying to cache a realization
  562. // in this logical brush yet
  563. pbrush->crFore((COLORREF)BO_NOTCACHED);
  564. // no cached realization yet (no need to
  565. // worry about crFore not being set when
  566. // someone tries to check for caching,
  567. // because we don't have a handle yet, and
  568. // we'll lock when we do get the handle,
  569. // forcing writes to flush)
  570. //
  571. // we are resetting the attributes / type.
  572. //
  573. if (bPen)
  574. {
  575. pbrush->ulStyle(HS_DITHEREDCLR);
  576. FLONG flOldAttrs = pbrush->flAttrs() &
  577. (BR_IS_PEN | BR_IS_OLDSTYLEPEN);
  578. pbrush->flAttrs(BR_IS_SOLID | flOldAttrs);
  579. }
  580. else
  581. {
  582. pbrush->ulStyle(HS_DITHEREDCLR);
  583. pbrush->flAttrs(BR_IS_SOLID | BR_DITHER_OK);
  584. }
  585. //
  586. // Set the uniqueness so the are-you-
  587. // really-dirty check in vInitBrush will
  588. // not think an old realization is still valid.
  589. //
  590. pbrush->ulBrushUnique(pbrush->ulGlobalBrushUnique());
  591. }
  592. else
  593. {
  594. WARNING1("Error, SetSolidBrush with cShare != 1");
  595. }
  596. HandleLock.vUnlock();
  597. }
  598. }
  599. if (prbrush)
  600. {
  601. prbrush->vRemoveRef(rbType);
  602. }
  603. }
  604. }
  605. #if DBG
  606. else
  607. {
  608. if (pbrush->bIsGlobal())
  609. {
  610. WARNING1("bIsGlobal\n");
  611. }
  612. if (pbrush->flAttrs() & BR_IS_SOLID)
  613. {
  614. WARNING1("BR_IS_SOLID is set\n");
  615. }
  616. WARNING("GreSetSolidBrush not passed a solid color brush\n");
  617. }
  618. #endif
  619. }
  620. #if DBG
  621. else
  622. {
  623. WARNING1("GreSetSolidBrush failed to lock down brush\n");
  624. }
  625. #endif
  626. return(bReturn);
  627. }
  628. /******************************Public*Routine******************************\
  629. * GreGetBrushColor
  630. *
  631. * Call for User to retrieve the color from any brush owned by any process
  632. * so User can repaint the background correctly in full drag. To make sure
  633. * we don't hose an app we need to hold the mult-lock while we do this so
  634. * any operation by the app (such as a Delete) will wait and not fail
  635. * because we're temporarily locking the brush down to peek inside of it.
  636. *
  637. * History:
  638. * 14-Jun-1994 -by- Patrick Haluptzok patrickh
  639. * Wrote it.
  640. \**************************************************************************/
  641. COLORREF GreGetBrushColor(HBRUSH hbr)
  642. {
  643. COLORREF clrRet = 0xFFFFFFFF;
  644. //
  645. // Grab the multi-lock so everyone waits while do our quick hack
  646. // to return the brush color.
  647. //
  648. MLOCKFAST mlo;
  649. //
  650. // Lock it down but don't check ownership because we want to succeed
  651. // no matter what.
  652. //
  653. //
  654. // using try except to make sure we will not crash
  655. // when a bad handle passed in.
  656. //
  657. __try
  658. {
  659. PENTRY pentry = &gpentHmgr[HmgIfromH(hbr)];
  660. PBRUSH pbrush = (PBRUSH)(pentry->einfo.pobj);
  661. if (pbrush)
  662. {
  663. if ((pbrush->ulStyle() == HS_SOLIDCLR) ||
  664. (pbrush->ulStyle() == HS_DITHEREDCLR))
  665. {
  666. clrRet = pbrush->crColor();
  667. }
  668. }
  669. }
  670. __except(EXCEPTION_EXECUTE_HANDLER)
  671. {
  672. WARNING1("GreGetBrushColor - bad handle passed in\n");
  673. }
  674. return(clrRet);
  675. }
  676. /******************************Public*Routine******************************\
  677. * BRUSHMEMOBJ::BRUSHMEMOBJ
  678. *
  679. * Creates hatched brushes and solid color brushes.
  680. *
  681. * History:
  682. * 29-Oct-1992 -by- Michael Abrash [mikeab]
  683. * changed to get handle only after fully initialized
  684. *
  685. * Wed 26-Feb-1992 -by- Patrick Haluptzok [patrickh]
  686. * rewrote to subsume other constructors, add new hatch styles.
  687. *
  688. * Sun 19-May-1991 -by- Patrick Haluptzok [patrickh]
  689. * Wrote it.
  690. \**************************************************************************/
  691. BRUSHMEMOBJ::BRUSHMEMOBJ(COLORREF cr, ULONG ulStyle_, BOOL bPen, BOOL bSharedMem)
  692. {
  693. if (ulStyle_ > HS_NULL)
  694. {
  695. WARNING1("Invalid style type\n");
  696. pbp.pbr = NULL;
  697. return;
  698. }
  699. PBRUSH pbrush;
  700. if ((pbp.pbr = pbrush = pbrAllocBrush(bPen)) == NULL)
  701. {
  702. WARNING1("Brush allocation failed\n");
  703. return;
  704. }
  705. pbrush->crColor(cr);
  706. pbrush->ulStyle(ulStyle_);
  707. pbrush->hbmPattern(0);
  708. pbrush->AttrFlags(0);
  709. if (ulStyle_ < HS_DDI_MAX)
  710. {
  711. // The old hatch brushes have been extended to include all the default
  712. // patterns passed back by the driver. There are 19 default pattens.
  713. pbrush->flAttrs(BR_IS_HATCH | BR_NEED_BK_CLR | BR_IS_MASKING);
  714. goto CreateHandle;
  715. }
  716. // Handle the other brush types
  717. switch(ulStyle_)
  718. {
  719. case HS_SOLIDCLR:
  720. pbrush->flAttrs(BR_IS_SOLID);
  721. break;
  722. case HS_DITHEREDCLR:
  723. pbrush->flAttrs(BR_IS_SOLID | BR_DITHER_OK);
  724. break;
  725. case HS_SOLIDTEXTCLR:
  726. pbrush->flAttrs(BR_IS_SOLID | BR_NEED_FG_CLR);
  727. break;
  728. case HS_DITHEREDTEXTCLR:
  729. pbrush->flAttrs(BR_IS_SOLID | BR_NEED_FG_CLR | BR_DITHER_OK);
  730. break;
  731. case HS_SOLIDBKCLR:
  732. pbrush->flAttrs(BR_IS_SOLID | BR_NEED_BK_CLR);
  733. break;
  734. case HS_DITHEREDBKCLR:
  735. pbrush->flAttrs(BR_IS_SOLID | BR_NEED_BK_CLR | BR_DITHER_OK);
  736. break;
  737. case HS_NULL:
  738. pbrush->flAttrs(BR_IS_NULL);
  739. break;
  740. default:
  741. RIP("ERROR BRUSHMEMOBJ hatches invalid type");
  742. }
  743. // Now that everything is set up, create the handle and expose this logical
  744. // brush
  745. CreateHandle:
  746. if (HmgInsertObject(pbrush, HMGR_ALLOC_ALT_LOCK, BRUSH_TYPE) == 0)
  747. {
  748. FREEOBJ(pbrush, BRUSH_TYPE);
  749. pbp.pbr = NULL;
  750. }
  751. else
  752. {
  753. if (bSharedMem)
  754. {
  755. //
  756. // Setup the user mode BRUSHATTR
  757. //
  758. PBRUSHATTR pUser = (PBRUSHATTR)HmgAllocateObjectAttr();
  759. if (pUser)
  760. {
  761. HANDLELOCK BrushLock;
  762. BrushLock.bLockHobj((HOBJ)pbrush->hHmgr,BRUSH_TYPE);
  763. if (BrushLock.bValid())
  764. {
  765. PENTRY pent = BrushLock.pentry();
  766. //
  767. // fill up the brushattr
  768. //
  769. *pUser = pbrush->_Brushattr;
  770. pent->pUser = (PVOID)pUser;
  771. pbrush->pBrushattr(pUser);
  772. BrushLock.vUnlock();
  773. }
  774. }
  775. }
  776. }
  777. }
  778. /******************************Public*Routine******************************\
  779. * EBRUSHOBJ::vInitBrush
  780. *
  781. * Initializes the brush user object. If the color can be represented
  782. * without dithering, we set iSolidColor.
  783. *
  784. * History:
  785. * Tue 08-Dec-1992 -by- Michael Abrash [mikeab]
  786. * Rewrote for speed.
  787. *
  788. * Sun 23-Jun-1991 -by- Patrick Haluptzok [patrickh]
  789. * Wrote it.
  790. \**************************************************************************/
  791. VOID
  792. EBRUSHOBJ::vInitBrush(
  793. PDC pdc, // current dc or a fake dc with only back/foreground clr info
  794. PBRUSH pbrushIn, // Current logical brush
  795. XEPALOBJ palDC, // Target's DC palette
  796. XEPALOBJ palSurf, // Target's surface palette
  797. SURFACE *pSurface, // Target surface
  798. BOOL bCanDither // If FALSE then never dither
  799. )
  800. {
  801. // Note: If more members of pdc are accessed in the future, then code must be
  802. // added in drvsup.cxx to initialize the members in each place a fake DC
  803. // object is initialized. There's also a fake DC in bDynamicModeChange in
  804. // opendc.cxx which must be updated.
  805. // If the palSurf isn't valid, then the target is a bitmap for a palette
  806. // managed device; therefore the palette means nothing until we actually blt,
  807. // and only the DC palette is relevant. Likewise, if the target is a palette
  808. // managed surface, the brush is realized as indices into the logical palette,
  809. // and unless the logical palette is changed, the brush doesn't need to be
  810. // rerealized. This causes us effectively to check the logical palette time
  811. // twice, but that's cheaper than checking whether we need to check the surface
  812. // palette time and then possibly checking it.
  813. ULONG ulSurfTime = (palSurf.bValid() && !palSurf.bIsPalManaged()) ?
  814. palSurf.ulTime() : 1;
  815. #if DBG
  816. bo_inits++;
  817. #endif
  818. // If the brush really is dirty, we have to set this anyway; if it's not dirty,
  819. // this takes care of the case where the surface has changed out from under us,
  820. // and then a realization is required and we would otherwise fault trying to
  821. // access the target surface structure in the process of realization.
  822. psoTarg1 = pSurface; // surface for which brush is realized
  823. // The journaling code depends on this
  824. // being set correctly. This has the PDEV
  825. // for the device it's selected into.
  826. COLORREF crTextDC = pdc->crTextClr();
  827. COLORREF crBackDC = pdc->crBackClr();
  828. LONG lIcmModeDC = pdc->lIcmMode();
  829. HANDLE hcmXformDC = pdc->hcmXform();
  830. // See if the brush really isn't dirty and doesn't need to be rerealized
  831. if ( ( pbrushIn->ulBrushUnique() == _ulUnique ) &&
  832. (!bCareAboutFg() || (crCurrentText() == crTextDC) ) &&
  833. (!bCareAboutBg() || (crCurrentBack() == crBackDC) ) &&
  834. (palDC.ulTime() == ulDCPalTime()) &&
  835. (ulSurfTime == ulSurfPalTime()) &&
  836. (pbrushIn != gpbrDCBrush)&&
  837. (pbrushIn != gpbrDCPen) &&
  838. (lIcmMode() == lIcmModeDC) &&
  839. (hcmXform() == hcmXformDC) &&
  840. (bCanDither == _bCanDither))
  841. {
  842. #if DBG
  843. bo_notdirty++;
  844. #endif
  845. return;
  846. }
  847. // Get Cached Values
  848. flAttrs = pbrushIn->flAttrs();
  849. // Remember the characteristics of the brush
  850. _pbrush = pbrushIn;
  851. _ulUnique = pbrushIn->ulBrushUnique(); // brush uniqueness
  852. crCurrentText1 = crTextDC; // text color at realization time
  853. crCurrentBack1 = crBackDC; // background color at realization time
  854. _ulDCPalTime = palDC.ulTime(); // DC palette set time at realization time
  855. _ulSurfPalTime = ulSurfTime; // surface palette set time at realization time
  856. _bCanDither = bCanDither; // dither enabled?
  857. // Initialize ICM stuffs
  858. BOOL bCMYKColorSolid = FALSE;
  859. flColorType = 0; // Initialized with zero.
  860. // Set icm modes
  861. if (IS_ICM_ON(lIcmModeDC))
  862. {
  863. BOOL bIcmBrush = FALSE;
  864. // color translation should happen, check we have nessesary data for ICM.
  865. if (flAttrs & (BR_IS_SOLID|BR_IS_HATCH|BR_IS_MONOCHROME))
  866. {
  867. if (IS_ICM_HOST(lIcmModeDC))
  868. {
  869. // DC attributes should have ICM-ed color.
  870. //
  871. // (or with null-ColorTransform, no color translation happen)
  872. if (flAttrs & (BR_IS_SOLID|BR_IS_MONOCHROME))
  873. {
  874. if ((flAttrs & (BR_NEED_FG_CLR|BR_NEED_BK_CLR)) ||
  875. (pbrushIn == gpbrDCBrush) || (pbrushIn == gpbrDCPen))
  876. {
  877. bIcmBrush = TRUE;
  878. }
  879. }
  880. if (bIcmBrush == FALSE)
  881. {
  882. if (pbrushIn->bIsPen())
  883. {
  884. if ((hcmXformDC == NULL) || pdc->bValidIcmPenColor())
  885. {
  886. bIcmBrush = TRUE;
  887. }
  888. else
  889. {
  890. ICMMSG(("vInitBrush():ERROR: No ICMed pen color for this brush\n"));
  891. }
  892. }
  893. else
  894. {
  895. if ((hcmXformDC == NULL) || pdc->bValidIcmBrushColor())
  896. {
  897. bIcmBrush = TRUE;
  898. }
  899. else
  900. {
  901. ICMMSG(("vInitBrush():ERROR: No ICMed brush color for this brush\n"));
  902. }
  903. }
  904. }
  905. }
  906. else // other ICM modes (Device and Apps)
  907. {
  908. bIcmBrush = TRUE;
  909. }
  910. }
  911. else if (flAttrs & BR_IS_DIB)
  912. {
  913. if (IS_ICM_HOST(lIcmModeDC))
  914. {
  915. // Brush should have ICM-ed DIB
  916. //
  917. // (or with null-ColorTransform, no color translation happen)
  918. if ((hcmXformDC == NULL) || pbrushIn->hFindIcmDIB(hcmXformDC))
  919. {
  920. bIcmBrush = TRUE;
  921. }
  922. else
  923. {
  924. ICMMSG(("vInitBrush():ERROR: No ICMed DIB for this brush\n"));
  925. }
  926. }
  927. else // other ICM modes (Device and Apps)
  928. {
  929. bIcmBrush = TRUE;
  930. }
  931. }
  932. else
  933. {
  934. // Other stlyes, no ICM
  935. }
  936. if (bIcmBrush)
  937. {
  938. lIcmMode(lIcmModeDC); // ICM mode
  939. hcmXform(hcmXformDC); // ICM molor Transform handle
  940. // setup colortype flag.
  941. if (bIsAppsICM() || bIsHostICM())
  942. {
  943. flColorType |= BR_HOST_ICM;
  944. }
  945. else if (bIsDeviceICM())
  946. {
  947. flColorType |= BR_DEVICE_ICM;
  948. }
  949. // If the brush is solid, iSolidColor will have CMKY color. Otherwise,
  950. // iSolidColor will be 0xFFFFFFFF and flColorType does not have BR_CMYKCOLOR.
  951. bCMYKColorSolid = (bIsCMYKColor() && (flAttrs & BR_IS_SOLID));
  952. if (bCMYKColorSolid)
  953. {
  954. flColorType |= BR_CMYKCOLOR; // color type is CMYK color
  955. }
  956. }
  957. else
  958. {
  959. ICMMSG(("vInitBrush():This brush is not ICMed\n"));
  960. lIcmMode(DC_ICM_OFF); // ICM mode
  961. hcmXform(NULL); // ICM molor Transform handle
  962. }
  963. }
  964. else
  965. {
  966. lIcmMode(DC_ICM_OFF); // ICM mode
  967. hcmXform(NULL); // ICM molor Transform handle
  968. }
  969. // Get the target PDEV
  970. PDEVOBJ po(pSurface->hdev());
  971. ASSERTGDI(po.bValid(), "ERROR BRUSHOBJ PDEVOBJ");
  972. // Set palettes
  973. palDC1.ppalSet(palDC.ppalGet());
  974. palSurf1.ppalSet(palSurf.ppalGet());
  975. palMeta1.ppalSet(po.ppalSurfNotDynamic());
  976. _iMetaFormat = po.iDitherFormatNotDynamic();
  977. ASSERTGDI(pSurface != NULL, "ERROR BRUSHOBJ::bInit0");
  978. ASSERTGDI(palDC.bValid(), "ERROR BRUSHOBJ::bInit4");
  979. // Clean up what was already here
  980. // If this brush object had an engine brush realization, get rid of it
  981. if (pengbrush1 != (PENGBRUSH) NULL)
  982. {
  983. PRBRUSH prbrush = pengbrush1; // point to engine brush realization
  984. prbrush->vRemoveRef(RB_ENGINE); // decrement the reference count on the
  985. // realization and free the brush if
  986. // this is the last reference
  987. pengbrush1 = NULL; // mark that there's no realization
  988. }
  989. // If this brush object had a device brush realization, get rid of it
  990. if (pvRbrush != (PVOID) NULL)
  991. {
  992. PRBRUSH prbrush = (PDBRUSH)DBRUSHSTART(pvRbrush);
  993. // point to DBRUSH (pvRbrush points to
  994. // realization, which is at the end of DBRUSH)
  995. prbrush->vRemoveRef(RB_DRIVER);
  996. // decrement the reference count on the
  997. // realization and free the brush if
  998. // this is the last reference
  999. pvRbrush = NULL; // mark that there's no realization
  1000. }
  1001. // Remember the color so we do the realization code correctly later
  1002. // if it's a dithered brush. We may need this even if we have
  1003. // a hit in the cache since we have driver/engine distinction.
  1004. if (flAttrs & BR_IS_SOLID)
  1005. {
  1006. if (flAttrs & BR_NEED_FG_CLR)
  1007. {
  1008. crRealize = crCurrentText(); // use text brush
  1009. if (bIsHostICM())
  1010. crRealizeOrignal = pdc->ulTextClr();
  1011. }
  1012. else if (flAttrs & BR_NEED_BK_CLR)
  1013. {
  1014. crRealize = crCurrentBack(); // use back brush
  1015. if (bIsHostICM())
  1016. crRealizeOrignal = pdc->ulBackClr();
  1017. }
  1018. else if (pbrushIn == gpbrDCBrush)
  1019. {
  1020. crRealize = pdc->crDCBrushClr(); // use DC brush
  1021. if (bIsHostICM())
  1022. crRealizeOrignal = pdc->ulDCBrushClr();
  1023. }
  1024. else if (pbrushIn == gpbrDCPen)
  1025. {
  1026. crRealize = pdc->crDCPenClr(); // use DC pen
  1027. if (bIsHostICM())
  1028. crRealizeOrignal = pdc->ulDCPenClr();
  1029. }
  1030. else
  1031. {
  1032. crRealize = pbrushIn->crColor();
  1033. if (bIsHostICM())
  1034. {
  1035. crRealizeOrignal = crRealize;
  1036. if (pbrushIn->bIsPen())
  1037. {
  1038. if (pdc->bValidIcmPenColor())
  1039. {
  1040. crRealize = pdc->crIcmPenColor(); // use ICM translated pen
  1041. }
  1042. }
  1043. else
  1044. {
  1045. if (pdc->bValidIcmBrushColor())
  1046. {
  1047. crRealize = pdc->crIcmBrushColor(); // use ICM translated brush
  1048. }
  1049. }
  1050. }
  1051. }
  1052. }
  1053. else if (flAttrs & BR_IS_HATCH)
  1054. {
  1055. crRealize = pbrushIn->crColor();
  1056. if (bIsHostICM())
  1057. {
  1058. crRealizeOrignal = crRealize;
  1059. if (pbrushIn->bIsPen())
  1060. {
  1061. if (pdc->bValidIcmPenColor())
  1062. {
  1063. crRealize = pdc->crIcmPenColor();
  1064. }
  1065. }
  1066. else
  1067. {
  1068. if (pdc->bValidIcmBrushColor())
  1069. {
  1070. crRealize = pdc->crIcmBrushColor();
  1071. }
  1072. }
  1073. }
  1074. }
  1075. // See if there's a cached realization that we can use
  1076. // Note that the check for crFore MUST come first, because if and only if
  1077. // that field is not BO_NOTCACHED is there a valid cached realization.
  1078. #if DBG
  1079. bo_realize++;
  1080. if ( (pbrushIn->crFore() == BO_NOTCACHED) )
  1081. {
  1082. bo_missnotcached++;
  1083. }
  1084. else if ( pbrushIn->bCareAboutFg() &&
  1085. (pbrushIn->crFore() != crTextDC) )
  1086. {
  1087. bo_missfg++;
  1088. }
  1089. else if (pbrushIn->bCareAboutBg() &&
  1090. (pbrushIn->crBack() != crBackDC) )
  1091. {
  1092. bo_missbg++;
  1093. }
  1094. else if ( pbrushIn->ulPalTime() != ulDCPalTime() )
  1095. {
  1096. bo_misspaltime++;
  1097. }
  1098. else if ( pbrushIn->ulSurfTime() != ulSurfPalTime() )
  1099. {
  1100. bo_misssurftime++;
  1101. }
  1102. else
  1103. {
  1104. bo_cachehit++;
  1105. }
  1106. #endif
  1107. if (
  1108. (pbrushIn->crFore() != BO_NOTCACHED) &&
  1109. (
  1110. (!pbrushIn->bCareAboutFg()) ||
  1111. (pbrushIn->crFore() == crTextDC)
  1112. ) &&
  1113. (
  1114. (!pbrushIn->bCareAboutBg()) ||
  1115. (pbrushIn->crBack() == crBackDC)
  1116. ) &&
  1117. (pbrushIn->ulPalTime() == ulDCPalTime()) &&
  1118. (pbrushIn->ulSurfTime() == ulSurfPalTime()) &&
  1119. (pbrushIn->hdevRealization() == po.hdev()) &&
  1120. (pbrushIn != gpbrDCBrush) &&
  1121. (pbrushIn != gpbrDCPen)
  1122. )
  1123. {
  1124. // Uncache the realization according to the realization type (solid,
  1125. // driver realization, or engine realization)
  1126. if (pbrushIn->bCachedIsSolid())
  1127. {
  1128. // Retrieve the cached solid color and done
  1129. iSolidColor = (ULONG)pbrushIn->ulRealization();
  1130. crPaletteColor = pbrushIn->crPalColor();
  1131. }
  1132. else
  1133. {
  1134. // See whether this is an engine or driver realization
  1135. PRBRUSH prbrush = (PRBRUSH)pbrushIn->ulRealization();
  1136. if (pbrushIn->bIsEngine())
  1137. {
  1138. pengbrush1 = (PENGBRUSH)prbrush;
  1139. }
  1140. else
  1141. {
  1142. // Skip over the RBRUSH at the start of the DBRUSH, so that the
  1143. // driver doesn't see that
  1144. pvRbrush = (PVOID)(((PDBRUSH)prbrush)->aj);
  1145. }
  1146. // Whether this was an engine or driver realization, now we've got
  1147. // it selected into another DC, so increment the reference count
  1148. // so it won't get deleted until it's no longer selected into any
  1149. // DC and the logical brush no longer exists
  1150. prbrush->vAddRef();
  1151. // Indicate that this is a pattern brush
  1152. iSolidColor = 0xffffffff;
  1153. crPaletteColor = pbrushIn->crPalColor();
  1154. }
  1155. // Nothing more to do once we've found that the realization is cached;
  1156. // this tells us all we hoped to find out in this call, either the
  1157. // solid color for the realization or else that the realization isn't
  1158. // solid (in which case we probably found the realization too, although
  1159. // if the cached realization is driver and this time the engine will do
  1160. // the drawing, or vice-versa, the cached realization won't help us)
  1161. return;
  1162. }
  1163. // If brush isn't based on color (if it is a bitmap or hatch), we're done
  1164. // here, because all we want to do is set iSolidColor if possible
  1165. if (!(flAttrs & BR_IS_SOLID))
  1166. {
  1167. iSolidColor = crPaletteColor = 0xffffffff;
  1168. return;
  1169. }
  1170. // See if we can find exactly the color we want
  1171. if (bCMYKColorSolid)
  1172. {
  1173. // crRealize is CMKY color just set it to iSolidColor
  1174. iSolidColor = crPaletteColor = crRealize;
  1175. }
  1176. else if (po.bCapsForceDither() && bCanDither)
  1177. {
  1178. // printer drivers may set the FORCEDITHER flag. In this case, we always
  1179. // want to dither brushes, even if they map to a color in the drivers palette.
  1180. iSolidColor = 0xffffffff;
  1181. crPaletteColor = crRealize;
  1182. }
  1183. else
  1184. {
  1185. iSolidColor =
  1186. ulGetMatchingIndexFromColorref(
  1187. palSurf,
  1188. palDC,
  1189. crRealize
  1190. );
  1191. crPaletteColor = rgbFromColorref(palSurf,
  1192. palDC,
  1193. crRealize
  1194. );
  1195. }
  1196. // Under CMYK color context, there is no dither.
  1197. if ((iSolidColor == 0xFFFFFFFF) && (!bCMYKColorSolid))
  1198. {
  1199. // Not an exact match. If we can dither, then we're done for now; we'll
  1200. // realize the brush when the driver wants it, so if all conditions are
  1201. // met for dithering this brush, then we're done
  1202. // we dither the brush if the caller says we can and if either the brush
  1203. // says it is ditherable or the driver has requested dithering.
  1204. if (((flAttrs & BR_DITHER_OK) || (po.bCapsForceDither())) &&
  1205. bCanDither)
  1206. {
  1207. // ...and the PDEV allows color dithering and either the bitmap is
  1208. // for a palette managed device, or if the surface and device
  1209. // palettes are the same palette, or if the destination surface is
  1210. // monochrome and the pdev has hooked mono dithering.
  1211. //
  1212. // Note: There is a dynamic mode change synchronization hole here
  1213. // between the time we check GCAPS_COLOR_DITHER/MONO_DITHER
  1214. // and the time that we go to actually realize the brush --
  1215. // the driver's capabilities may have changed in the mean
  1216. // time. Note that this will happen only when drawing to
  1217. // DIB based compatible bitmaps. Since it will be rare, and
  1218. // since we won't fall over, I'm letting it through...
  1219. if (
  1220. (
  1221. (
  1222. (!palSurf.bValid()) ||
  1223. (palSurf.ppalGet() == po.ppalSurfNotDynamic())
  1224. ) &&
  1225. (po.flGraphicsCapsNotDynamic() & GCAPS_COLOR_DITHER)
  1226. ) ||
  1227. (palSurf.bIsMonochrome() &&
  1228. (po.flGraphicsCapsNotDynamic() & GCAPS_MONO_DITHER)
  1229. )
  1230. )
  1231. {
  1232. // ...then we can dither this brush, so we can't set iSolidColor
  1233. // and we're done. Dithering will be done when the driver
  1234. // requests realization
  1235. //
  1236. crPaletteColor = crRealize;
  1237. return;
  1238. }
  1239. }
  1240. // We can't dither and there's no exact match, so find the nearest
  1241. // color and that'll have to do
  1242. if (pSurface->iFormat() == BMF_1BPP)
  1243. {
  1244. // For monochrome surface, we'll have background mapped to
  1245. // background and everything else mapped to foreground.
  1246. iSolidColor = ulGetNearestIndexFromColorref(
  1247. palSurf,
  1248. palDC,
  1249. crBackDC,
  1250. SE_DONT_SEARCH_EXACT_FIRST
  1251. );
  1252. crPaletteColor = rgbFromColorref(palSurf,
  1253. palDC,
  1254. crBackDC);
  1255. if (crBackDC != crRealize)
  1256. {
  1257. iSolidColor = 1 - iSolidColor;
  1258. // Obtain corresponding color from index.
  1259. PAL_ULONG ulPalTemp;
  1260. ulPalTemp.pal = palSurf.palentryGet(iSolidColor);
  1261. crPaletteColor = ulPalTemp.ul;
  1262. }
  1263. }
  1264. else
  1265. {
  1266. iSolidColor = ulGetNearestIndexFromColorref(
  1267. palSurf,
  1268. palDC,
  1269. crRealize,
  1270. SE_DONT_SEARCH_EXACT_FIRST
  1271. );
  1272. crPaletteColor = rgbFromColorref(palSurf,
  1273. palDC,
  1274. crRealize);
  1275. }
  1276. }
  1277. // See if we can cache this brush color in the logical brush; we can't if
  1278. // another realization has already been cached in the logical brush
  1279. // See vTryToCacheRealization, in BRUSHDDI.CXX, for a detailed explanation
  1280. // of caching in the logical brush
  1281. if ( !pbrushIn->bCacheGrabbed() )
  1282. {
  1283. // Try to grab the "can cache" flag; if we don't get it, someone just
  1284. // sneaked in and got it ahead of us, so we're out of luck and can't
  1285. // cache
  1286. if ( pbrushIn->bGrabCache() )
  1287. {
  1288. // We got the "can cache" flag, so now we can cache this realization
  1289. // in the logical brush
  1290. // These cache ID fields must be set before crFore, because crFore
  1291. // is the key that indicates when the cached realization is valid.
  1292. // If crFore is -1 when the logical brush is being realized, we
  1293. // just go realize the brush; if it's not -1, we check the cache ID
  1294. // fields to see if we can use the cached fields.
  1295. // InterlockedExchange() is used below to set crFore to make sure
  1296. // the cache ID fields are set before crFore
  1297. pbrushIn->crBack(crCurrentBack1);
  1298. pbrushIn->ulPalTime(ulDCPalTime());
  1299. pbrushIn->ulSurfTime(ulSurfPalTime());
  1300. pbrushIn->ulRealization(iSolidColor);
  1301. pbrushIn->crPalColor(crPaletteColor);
  1302. pbrushIn->SetSolidRealization();
  1303. // This must be set last, because once it's set, other selections
  1304. // of this logical brush will attempt to use the cached brush. The
  1305. // use of InterlockedExchange in this method enforces this
  1306. pbrushIn->crForeLocked(crCurrentText1);
  1307. // The realization is now cached in the logical brush
  1308. }
  1309. }
  1310. return;
  1311. }
  1312. /******************************Public*Routine******************************\
  1313. * EBRUSHOBJ::vNuke()
  1314. *
  1315. * Clean up framed EBRUSHOBJ
  1316. *
  1317. * History:
  1318. * 20-Mar-1992 -by- Donald Sidoroff [donalds]
  1319. * Wrote it.
  1320. \**************************************************************************/
  1321. VOID EBRUSHOBJ::vNuke()
  1322. {
  1323. if (pengbrush1 != (PENGBRUSH) NULL)
  1324. {
  1325. PRBRUSH prbrush = pengbrush1; // point to engine brush realization
  1326. prbrush->vRemoveRef(RB_ENGINE); // decrement the reference count on the
  1327. // realization and free the brush if
  1328. // this is the last reference
  1329. }
  1330. if (pvRbrush != (PVOID) NULL)
  1331. {
  1332. PRBRUSH prbrush = (PDBRUSH)DBRUSHSTART(pvRbrush);
  1333. // point to DBRUSH (pvRbrush points to
  1334. // realization, which is at the end of DBRUSH)
  1335. prbrush->vRemoveRef(RB_DRIVER);
  1336. // decrement the reference count on the
  1337. // realization and free the brush if
  1338. // this is the last reference
  1339. }
  1340. }
  1341. // This is the brusheng.cxx section
  1342. /******************************Public*Routine******************************\
  1343. * bInitBRUSHOBJ
  1344. *
  1345. * Initializes the default brushes and and the dclevel default values for
  1346. * brushes and pens.
  1347. *
  1348. * Explanation of the NULL brush (alias Hollow Brush)
  1349. * The Null brush is special. Only 1 is ever created
  1350. * (at initialization time in hbrNull). The only API's for
  1351. * getting a Null brush are CreateBrushIndirect and GetStockObject which
  1352. * both return "the 1 and only 1" Null brush. A Null brush is never
  1353. * realized by a driver or the engine. No output call should ever occur
  1354. * that requires a brush if the brush is NULL, the engine should stop
  1355. * these before they get to the driver.
  1356. *
  1357. * History:
  1358. * 20-May-1991 -by- Patrick Haluptzok patrickh
  1359. * Wrote it.
  1360. \**************************************************************************/
  1361. extern "C" BOOL bInitBrush(
  1362. int iBrush,
  1363. COLORREF cr,
  1364. DWORD dwHS,
  1365. PULONG_PTR pdw,
  1366. BOOL bEnableDither
  1367. )
  1368. {
  1369. BOOL bSuccess = FALSE;
  1370. BRUSHMEMOBJ brmo(cr,dwHS,FALSE,FALSE);
  1371. if (brmo.bValid())
  1372. {
  1373. brmo.vKeepIt();
  1374. brmo.vGlobal();
  1375. if (bEnableDither)
  1376. brmo.vEnableDither();
  1377. if (pdw)
  1378. *pdw = (ULONG_PTR)brmo.pbrush();
  1379. bSetStockObject(brmo.hbrush(),iBrush);
  1380. // init DcAttrDefault brush
  1381. if (iBrush == WHITE_BRUSH)
  1382. {
  1383. DcAttrDefault.hbrush = brmo.hbrush();
  1384. }
  1385. bSuccess = TRUE;
  1386. }
  1387. else
  1388. {
  1389. #if DBG
  1390. DbgPrint("couldn't create default brush %lx, %lx\n",cr,iBrush);
  1391. #endif
  1392. return(FALSE);
  1393. }
  1394. return(bSuccess);
  1395. }
  1396. BOOL bInitBRUSHOBJ()
  1397. {
  1398. if (!bInitBrush(WHITE_BRUSH,(COLORREF)RGB(0xFF,0xFF,0xFF),
  1399. HS_DITHEREDCLR,(PULONG_PTR)&dclevelDefault.pbrFill,FALSE) ||
  1400. !bInitBrush(BLACK_BRUSH, (COLORREF)RGB(0x0, 0x0, 0x0), HS_DITHEREDCLR,NULL,FALSE) ||
  1401. !bInitBrush(GRAY_BRUSH, (COLORREF)RGB(0x80,0x80,0x80),HS_DITHEREDCLR,NULL,TRUE) ||
  1402. !bInitBrush(DKGRAY_BRUSH,(COLORREF)RGB(0x40,0x40,0x40),HS_DITHEREDCLR,NULL,TRUE) ||
  1403. !bInitBrush(LTGRAY_BRUSH,(COLORREF)RGB(0xc0,0xc0,0xc0),HS_DITHEREDCLR,NULL,TRUE) ||
  1404. !bInitBrush(NULL_BRUSH, (COLORREF)0,HS_NULL,(PULONG_PTR)&gpbrNull,FALSE))
  1405. {
  1406. return(FALSE);
  1407. }
  1408. // Init default Null Pen
  1409. {
  1410. BRUSHMEMOBJ brmo((COLORREF) 0, HS_NULL, TRUE, FALSE); // TRUE signifies a pen
  1411. if (brmo.bValid())
  1412. {
  1413. brmo.vKeepIt();
  1414. brmo.vGlobal();
  1415. brmo.vSetOldStylePen();
  1416. brmo.flStylePen(PS_NULL);
  1417. brmo.lWidthPen(1);
  1418. HmgModifyHandleType((HOBJ)MODIFY_HMGR_TYPE(brmo.hbrush(),LO_PEN_TYPE));
  1419. bSetStockObject(brmo.hbrush(),NULL_PEN);
  1420. gpPenNull = (PPEN)brmo.pbrush();
  1421. }
  1422. else
  1423. {
  1424. WARNING("Failed Null Pen");
  1425. return(FALSE);
  1426. }
  1427. }
  1428. // Init default Black Pen
  1429. {
  1430. BRUSHMEMOBJ brmo((COLORREF) (RGB(0,0,0)), HS_DITHEREDCLR, TRUE, FALSE);
  1431. if (brmo.bValid())
  1432. {
  1433. brmo.vKeepIt();
  1434. brmo.vGlobal();
  1435. brmo.vSetOldStylePen();
  1436. brmo.flStylePen(PS_SOLID);
  1437. brmo.lWidthPen(0);
  1438. brmo.l_eWidthPen(IEEE_0_0F);
  1439. brmo.iJoin(JOIN_ROUND);
  1440. brmo.iEndCap(ENDCAP_ROUND);
  1441. brmo.pstyle((PFLOAT_LONG) NULL);
  1442. HmgModifyHandleType((HOBJ)MODIFY_HMGR_TYPE(brmo.hbrush(),LO_PEN_TYPE));
  1443. bSetStockObject(brmo.hbrush(),BLACK_PEN);
  1444. DcAttrDefault.hpen = (HPEN)brmo.hbrush();
  1445. dclevelDefault.pbrLine = brmo.pbrush();
  1446. }
  1447. else
  1448. {
  1449. WARNING("failed black pen");
  1450. return(FALSE);
  1451. }
  1452. }
  1453. // Init default White Pen
  1454. {
  1455. BRUSHMEMOBJ brmo((COLORREF) (RGB(0xFF,0xFF,0xFF)), HS_DITHEREDCLR, TRUE, FALSE);
  1456. if (brmo.bValid())
  1457. {
  1458. brmo.vKeepIt();
  1459. brmo.vGlobal();
  1460. brmo.vSetOldStylePen();
  1461. brmo.flStylePen(PS_SOLID);
  1462. brmo.lWidthPen(0);
  1463. brmo.l_eWidthPen(IEEE_0_0F);
  1464. brmo.iJoin(JOIN_ROUND);
  1465. brmo.iEndCap(ENDCAP_ROUND);
  1466. brmo.pstyle((PFLOAT_LONG) NULL);
  1467. HmgModifyHandleType((HOBJ)MODIFY_HMGR_TYPE(brmo.hbrush(),LO_PEN_TYPE));
  1468. bSetStockObject(brmo.hbrush(),WHITE_PEN);
  1469. }
  1470. else
  1471. {
  1472. WARNING("Failed white pen");
  1473. return(FALSE);
  1474. }
  1475. }
  1476. // Init the stock DC Pen
  1477. {
  1478. BRUSHMEMOBJ brmo((COLORREF) (RGB(0,0,0)), HS_DITHEREDCLR, TRUE, FALSE);
  1479. if (brmo.bValid())
  1480. {
  1481. brmo.vKeepIt();
  1482. brmo.vGlobal();
  1483. brmo.vSetOldStylePen();
  1484. brmo.flStylePen(PS_SOLID);
  1485. brmo.lWidthPen(0);
  1486. brmo.l_eWidthPen(IEEE_0_0F);
  1487. brmo.iJoin(JOIN_ROUND);
  1488. brmo.iEndCap(ENDCAP_ROUND);
  1489. brmo.pstyle((PFLOAT_LONG) NULL);
  1490. HmgModifyHandleType((HOBJ)MODIFY_HMGR_TYPE(brmo.hbrush(),LO_PEN_TYPE));
  1491. bSetStockObject(brmo.hbrush(),DC_PEN);
  1492. ghbrDCPen = brmo.hbrush();
  1493. gpbrDCPen = brmo.pbrush();
  1494. }
  1495. else
  1496. {
  1497. WARNING("Failed DC pen");
  1498. return(FALSE);
  1499. }
  1500. }
  1501. // init the text brush
  1502. {
  1503. BRUSHMEMOBJ brmo((COLORREF) (RGB(0,0,0)),HS_DITHEREDTEXTCLR,FALSE,FALSE);
  1504. if (brmo.bValid())
  1505. {
  1506. brmo.vKeepIt();
  1507. brmo.vGlobal();
  1508. ghbrText = brmo.hbrush();
  1509. gpbrText = brmo.pbrush();
  1510. }
  1511. else
  1512. {
  1513. WARNING("Could not create default text brush");
  1514. return(FALSE);
  1515. }
  1516. }
  1517. // init the background brush
  1518. {
  1519. BRUSHMEMOBJ brmo((COLORREF) (RGB(0xff,0xff,0xff)),HS_DITHEREDBKCLR,FALSE,FALSE);
  1520. if (brmo.bValid())
  1521. {
  1522. brmo.vKeepIt();
  1523. brmo.vGlobal();
  1524. ghbrBackground = brmo.hbrush();
  1525. gpbrBackground = brmo.pbrush();
  1526. }
  1527. else
  1528. {
  1529. WARNING("Could not create default background brush");
  1530. return(FALSE);
  1531. }
  1532. }
  1533. // init the global pattern gray brush
  1534. {
  1535. static WORD patGray[8] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
  1536. HBITMAP hbmGray;
  1537. hbmGray = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)patGray);
  1538. if (hbmGray == (HBITMAP) 0)
  1539. {
  1540. WARNING1("bInitBRUSHOBJ failed GreCreateBitmap\n");
  1541. return(FALSE);
  1542. }
  1543. ghbrGrayPattern = GreCreatePatternBrush(hbmGray);
  1544. if (ghbrGrayPattern == (HBRUSH) 0)
  1545. {
  1546. WARNING1("bInitBRUSHOBJ failed GreCreatePatternBrush\n");
  1547. return(FALSE);
  1548. }
  1549. GreDeleteObject(hbmGray);
  1550. GreSetBrushOwnerPublic((HBRUSH)ghbrGrayPattern);
  1551. }
  1552. // init the stock DC brush
  1553. {
  1554. BRUSHMEMOBJ brmo((COLORREF) (RGB(0xff,0xff,0xff)),HS_DITHEREDCLR,FALSE,FALSE);
  1555. if (brmo.bValid())
  1556. {
  1557. brmo.vKeepIt();
  1558. brmo.vGlobal();
  1559. bSetStockObject(brmo.hbrush(), DC_BRUSH);
  1560. ghbrDCBrush = brmo.hbrush();
  1561. gpbrDCBrush = brmo.pbrush();
  1562. }
  1563. else
  1564. {
  1565. WARNING("Could not create direct dc brush");
  1566. return(FALSE);
  1567. }
  1568. }
  1569. return(TRUE);
  1570. }
  1571. /******************************Public*Routine******************************\
  1572. * GreSelectBrush
  1573. *
  1574. * Selects the given brush into the given DC. Fast SelectObject
  1575. *
  1576. * History:
  1577. * Thu 21-Oct-1993 -by- Patrick Haluptzok [patrickh]
  1578. * wrote it.
  1579. \**************************************************************************/
  1580. HBRUSH GreSelectBrush(HDC hdc, HBRUSH hbrush)
  1581. {
  1582. HBRUSH hbrReturn = (HBRUSH) 0;
  1583. //
  1584. // Try to lock the DC. If we fail, we just return failure.
  1585. //
  1586. XDCOBJ dco(hdc);
  1587. if (dco.bValid())
  1588. {
  1589. //
  1590. // call DC locked version
  1591. //
  1592. hbrReturn = GreDCSelectBrush(dco.pdc,hbrush);
  1593. dco.vUnlockFast();
  1594. }
  1595. return(hbrReturn);
  1596. }
  1597. /******************************Public*Routine******************************\
  1598. * GreDCSelectBrush
  1599. *
  1600. * Select brush with dc already locked
  1601. *
  1602. * Arguments:
  1603. *
  1604. * pdc - locked DC pointer
  1605. * hbrush - brush to select
  1606. *
  1607. * Return Value:
  1608. *
  1609. * Old hbrush or NULL
  1610. *
  1611. * History:
  1612. *
  1613. * 19-May-1995 : copied from GreSelectBrush
  1614. *
  1615. \**************************************************************************/
  1616. HBRUSH
  1617. GreDCSelectBrush(
  1618. PDC pdc,
  1619. HBRUSH hbrush
  1620. )
  1621. {
  1622. HBRUSH hbrReturn = (HBRUSH) 0;
  1623. PBRUSH pbrush = NULL;
  1624. XDCOBJ dco;
  1625. dco.pdc = pdc;
  1626. if (dco.bValid())
  1627. {
  1628. HBRUSH hbrOld;
  1629. //
  1630. // The DC is locked. Set the return value to the old brush in the DC.
  1631. //
  1632. hbrOld = (HBRUSH) (dco.pdc->pbrushFill())->hGet();
  1633. //
  1634. // the return value should be the one cached in the dc
  1635. //
  1636. hbrReturn = dco.pdc->hbrush();
  1637. //
  1638. // If the new brush is the same as the old brush, nothing to do.
  1639. //
  1640. if (DIFFHANDLE(hbrush,hbrOld))
  1641. {
  1642. //
  1643. // Try to lock down the logical brush so we can get the pointer out.
  1644. //
  1645. pbrush = (BRUSH *)HmgShareCheckLock((HOBJ)hbrush, BRUSH_TYPE);
  1646. if (pbrush)
  1647. {
  1648. //
  1649. // Undo the lock from when the brush was selected.
  1650. //
  1651. DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushFill());
  1652. //
  1653. // Changing pbrushfill, set flag to force re-realization
  1654. //
  1655. dco.ulDirtyAdd(DIRTY_FILL);
  1656. //
  1657. // Save the pointer to the logical brush in the DC. We don't
  1658. // unlock the logical brush, because the alt lock count in the
  1659. // logical brush is the reference count for DCs in which the brush
  1660. // is currently selected; this protects us from having the actual
  1661. // logical brush deleted while it's selected into a DC, and allows
  1662. // us to reference the brush with a pointer rather than having to
  1663. // lock down the logical brush every time.
  1664. //
  1665. dco.pdc->pbrushFill(pbrush);
  1666. }
  1667. else
  1668. {
  1669. WARNING1("SelectBrush got invalid brush handle\n");
  1670. hbrReturn = NULL;
  1671. }
  1672. }
  1673. else
  1674. {
  1675. pbrush = dco.pdc->pbrushFill();
  1676. }
  1677. if (pbrush != NULL)
  1678. {
  1679. if (hbrReturn != NULL)
  1680. {
  1681. //
  1682. // must still check brush for new color
  1683. //
  1684. PBRUSHATTR pUser = pbrush->_pBrushattr;
  1685. //
  1686. // if the brush handle is a cached solid brush,
  1687. // call GreSetSolidBrushInternal to change the color
  1688. //
  1689. if (pUser != &pbrush->_Brushattr)
  1690. {
  1691. if (pUser->AttrFlags & ATTR_NEW_COLOR)
  1692. {
  1693. //
  1694. // force re-realization in case handle was same
  1695. //
  1696. dco.ulDirtyAdd(DIRTY_FILL);
  1697. //
  1698. // set the new color for the cached brush.
  1699. // Note: since pbrush is pulled straight
  1700. // from the DC, it's reference count will
  1701. // be 1, which is needed by SetSolidBrush
  1702. //
  1703. if (!GreSetSolidBrushLight(pbrush,pUser->lbColor,FALSE))
  1704. {
  1705. WARNING1("GreSyncbrush failed to setsolidbrushiternal\n");
  1706. }
  1707. pUser->AttrFlags &= ~ATTR_NEW_COLOR;
  1708. }
  1709. }
  1710. }
  1711. dco.pdc->hbrush(hbrush);
  1712. dco.pdc->ulDirtySub(DC_BRUSH_DIRTY);
  1713. }
  1714. }
  1715. return(hbrReturn);
  1716. }
  1717. /******************************Public*Routine******************************\
  1718. * GreDCSelectPen
  1719. * Selects a hpen into the given pdc
  1720. *
  1721. * Arguments:
  1722. *
  1723. * pdc - locked dc
  1724. * hpen - hpen to select
  1725. *
  1726. * Return Value:
  1727. *
  1728. * old hpen
  1729. *
  1730. * History:
  1731. *
  1732. * 29-Jan-1996 -by- Mark Enstrom [marke]
  1733. *
  1734. \**************************************************************************/
  1735. HPEN GreDCSelectPen(
  1736. PDC pdc,
  1737. HPEN hpen
  1738. )
  1739. {
  1740. HPEN hpReturn = (HPEN) NULL;
  1741. PPEN ppen = NULL;
  1742. //
  1743. // Try to lock the DC. If we fail, we just return failure.
  1744. //
  1745. XDCOBJ dco;
  1746. dco.pdc = pdc;
  1747. if (dco.bValid())
  1748. {
  1749. HPEN hpOld;
  1750. BOOL bRealize = FALSE;
  1751. //
  1752. // hpOld is the pen (LINE BRUSH) currently realized in the DC
  1753. //
  1754. hpOld = (HPEN) (dco.pdc->pbrushLine())->hGet();
  1755. //
  1756. // Set the return value to the old pen in the DCATTR.
  1757. // This is the last hpen the user selected
  1758. //
  1759. hpReturn = (HPEN)dco.pdc->hpen();
  1760. //
  1761. // If the new pen is the same as the old pen, nothing to do.
  1762. //
  1763. if (DIFFHANDLE(hpen, hpOld))
  1764. {
  1765. //
  1766. // Try to lock down the logical brush so we can get the pointer out.
  1767. //
  1768. ppen = (PEN *)HmgShareCheckLock((HOBJ)hpen, BRUSH_TYPE);
  1769. if (ppen && ppen->bIsPen())
  1770. {
  1771. //
  1772. // Undo the lock from when the pen was selected.
  1773. //
  1774. DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushLine());
  1775. //
  1776. // Mark line relization is invalid.
  1777. //
  1778. dco.ulDirtyAdd(DIRTY_LINE);
  1779. //
  1780. // Save the pointer to the logical brush in the DC. We don't
  1781. // unlock the logical brush, because the alt lock count in the
  1782. // logical brush is the reference count for DCs in which the brush
  1783. // is currently selected; this protects us from having the actual
  1784. // logical brush deleted while it's selected into a DC, and allows
  1785. // us to reference the brush with a pointer rather than having to
  1786. // lock down the logical brush every time.
  1787. //
  1788. dco.pdc->pbrushLine(ppen);
  1789. //
  1790. // The pen changed, so realize the new LINEATTRS, based on
  1791. // the current world transform.
  1792. //
  1793. bRealize = TRUE;
  1794. }
  1795. else
  1796. {
  1797. WARNING1("SelectPen got invalid pen handle\n");
  1798. //
  1799. // If this is not pen, can't select it as pen.
  1800. //
  1801. if (ppen)
  1802. {
  1803. DEC_SHARE_REF_CNT(ppen);
  1804. ppen = NULL;
  1805. }
  1806. hpReturn = NULL;
  1807. }
  1808. }
  1809. else
  1810. {
  1811. ppen = (PPEN)dco.pdc->pbrushLine();
  1812. }
  1813. //
  1814. // In case the handle stays the same, but the pen is new
  1815. // due to re-use of a user hpen, so re-realize it.
  1816. //
  1817. if (ppen != (PPEN) NULL)
  1818. {
  1819. if (hpReturn != NULL)
  1820. {
  1821. PBRUSHATTR pUser = ppen->_pBrushattr;
  1822. //
  1823. // if the brush handle is a cached solid brush,
  1824. // call GreSetSolidBrushInternal to change the color
  1825. //
  1826. if (pUser != &ppen->_Brushattr)
  1827. {
  1828. if (pUser->AttrFlags & ATTR_NEW_COLOR)
  1829. {
  1830. //
  1831. // set the new color for the cached brush.
  1832. // Note: since pbrush is pulled straight
  1833. // from the DC, it's reference count will
  1834. // be 1, which is needed by SetSolidBrush
  1835. //
  1836. if (!GreSetSolidBrushLight(ppen,pUser->lbColor,TRUE))
  1837. {
  1838. WARNING ("GreDCSelectPen failed to setsolidbrushiternal\n");
  1839. }
  1840. dco.ulDirtyAdd(DIRTY_LINE);
  1841. pUser->AttrFlags &= ~ATTR_NEW_COLOR;
  1842. bRealize = TRUE;
  1843. }
  1844. }
  1845. if (bRealize)
  1846. {
  1847. //
  1848. // The pen changed, so realize the new LINEATTRS, based on
  1849. // the current world transform.
  1850. //
  1851. EXFORMOBJ exo(dco, WORLD_TO_DEVICE);
  1852. dco.pdc->vRealizeLineAttrs(exo);
  1853. LINEATTRS *pla = dco.plaRealized();
  1854. }
  1855. }
  1856. dco.pdc->hpen(hpen);
  1857. dco.pdc->ulDirtySub(DC_PEN_DIRTY);
  1858. }
  1859. }
  1860. return(hpReturn);
  1861. }
  1862. /******************************Public*Routine******************************\
  1863. * GreSelectPen
  1864. *
  1865. * Selects the given brush into the given DC. Fast SelectObject
  1866. *
  1867. * History:
  1868. * Thu 21-Oct-1993 -by- Patrick Haluptzok [patrickh]
  1869. * wrote it.
  1870. \**************************************************************************/
  1871. HPEN GreSelectPen(HDC hdc, HPEN hpen)
  1872. {
  1873. HPEN hpenReturn = (HPEN) 0;
  1874. //
  1875. // Try to lock the DC. If we fail, we just return failure.
  1876. //
  1877. XDCOBJ dco(hdc);
  1878. if (dco.bValid())
  1879. {
  1880. //
  1881. // call DC locked version
  1882. //
  1883. hpenReturn = GreDCSelectPen(dco.pdc,hpen);
  1884. dco.vUnlockFast();
  1885. }
  1886. return(hpenReturn);
  1887. }
  1888. /******************************Public*Routine******************************\
  1889. * bDeleteBrush
  1890. *
  1891. * This will delete the brush. The brush can only be deleted if it's not
  1892. * global and not being used by anyone else.
  1893. *
  1894. * History:
  1895. *
  1896. * 7-Feb-1996 -by- Mark Enstrom [marke]
  1897. * Add PEB caching for brush and pen objects
  1898. * 23-May-1991 -by- Patrick Haluptzok patrickh
  1899. * Wrote it.
  1900. \**************************************************************************/
  1901. BOOL bDeleteBrush(HBRUSH hbrush, BOOL bCleanup)
  1902. {
  1903. PBRUSHPEN pbp;
  1904. BOOL bReturn = TRUE;
  1905. HBRUSH hbrushNew;
  1906. BOOL bDelete = TRUE;
  1907. PBRUSHATTR pUser = NULL;
  1908. PENTRY pentTmp;
  1909. BOOL bMakeNonStock = FALSE;
  1910. //
  1911. // check handle for user-mode brush
  1912. //
  1913. if (!bCleanup)
  1914. {
  1915. HANDLELOCK BrushLock;
  1916. BrushLock.bLockHobj((HOBJ)hbrush,BRUSH_TYPE);
  1917. if (BrushLock.bValid())
  1918. {
  1919. POBJ pobj = BrushLock.pObj();
  1920. pUser = (PBRUSHATTR)BrushLock.pUser();
  1921. ASSERTGDI(pobj->cExclusiveLock == 0, "deletebrush - exclusive lock not 0\n");
  1922. //
  1923. // If Brush is still in use, mark for lazy deletion and return true
  1924. //
  1925. if (BrushLock.ShareCount() > 0)
  1926. {
  1927. ((PBRUSH)pobj)->AttrFlags(ATTR_TO_BE_DELETED);
  1928. bDelete = FALSE;
  1929. }
  1930. else if (pUser != (PBRUSHATTR)NULL)
  1931. {
  1932. if (!(pUser->AttrFlags & ATTR_CACHED))
  1933. {
  1934. BOOL bPen = ((PPEN)pobj)->bIsPen();
  1935. INT iType = LO_TYPE(hbrush);
  1936. #if DBG
  1937. //
  1938. // make sure handle type agrees with bPen
  1939. //
  1940. if (bPen)
  1941. {
  1942. ASSERTGDI(((iType == LO_PEN_TYPE) || (iType == LO_EXTPEN_TYPE)),
  1943. "bDeleteBrush Error: PEN TYPE NOT LO_PEN OR LO_EXTPEN");
  1944. }
  1945. else
  1946. {
  1947. ASSERTGDI((iType == LO_BRUSH_TYPE),
  1948. "bDeleteBrush error: BRUSH type not LO_BRUSH_TYPE");
  1949. }
  1950. #endif
  1951. //
  1952. // try to cache the solid brush
  1953. // don't cache LO_EXTPEN_TYPE
  1954. //
  1955. if ((((PBRUSH)pobj)->flAttrs() & BR_IS_SOLID) &&
  1956. (!bPen || iType != LO_EXTPEN_TYPE))
  1957. {
  1958. BOOL bStatus;
  1959. bStatus = bPEBCacheHandle(hbrush,bPen?PenHandle:BrushHandle,(POBJECTATTR)pUser,(PENTRY)BrushLock.pentry());
  1960. if (bStatus)
  1961. {
  1962. bDelete = FALSE;
  1963. }
  1964. }
  1965. }
  1966. else
  1967. {
  1968. //
  1969. // brush is already cached
  1970. //
  1971. WARNING1("Trying to delete brush marked as cached\n");
  1972. bDelete = FALSE;
  1973. }
  1974. }
  1975. if (bDelete)
  1976. {
  1977. if (bMakeNonStock = ((PBRUSH)pobj)->bIsMakeNonStock())
  1978. {
  1979. ((PBRUSH)pobj)->vClearMakeNonStock();
  1980. }
  1981. }
  1982. BrushLock.vUnlock();
  1983. }
  1984. }
  1985. if (bDelete)
  1986. {
  1987. if (bMakeNonStock)
  1988. {
  1989. STOCKINFO("Brush(%p) is marked MakeNonStock. Doing it\n", hbrush);
  1990. if(!GreMakeBrushNonStock(hbrush))
  1991. STOCKWARNING("GreMakeBrushNonStock (%p) failed\n", hbrush);
  1992. }
  1993. //
  1994. // Try and remove handle from Hmgr. This will fail if the brush
  1995. // is locked down on any threads or if it has been marked global
  1996. // or undeletable.
  1997. //
  1998. pbp.pbr = (PBRUSH) HmgRemoveObject((HOBJ)hbrush, 0, 0, FALSE, BRUSH_TYPE);
  1999. if (pbp.pbr!= NULL)
  2000. {
  2001. //
  2002. // Free the style array memory if there is some and it's
  2003. // not pointing to our stock default styles:
  2004. //
  2005. if (pbp.pbr->bIsPen())
  2006. {
  2007. if ((pbp.ppen->pstyle() != (PFLOAT_LONG) NULL) &&
  2008. !pbp.ppen->bIsDefaultStyle())
  2009. {
  2010. //
  2011. // We don't set the field to NULL since this brush
  2012. // is on it's way out.
  2013. //
  2014. VFREEMEM(pbp.ppen->pstyle());
  2015. }
  2016. }
  2017. //
  2018. // Free the bitmap pattern in the brush.
  2019. //
  2020. if (pbp.pbr->hbmPattern())
  2021. {
  2022. //
  2023. // We don't set the field to NULL since this brush
  2024. // is on it's way out.
  2025. //
  2026. BOOL bTemp = bDeleteSurface((HSURF)pbp.pbr->hbmPattern());
  2027. ASSERTGDI(bTemp, "ERROR How could pattern brush failed deletion?");
  2028. }
  2029. //
  2030. // Un-reference count the realization cached in the logical brush,
  2031. // if any. We don't have to worry about anyone else being in the
  2032. // middle of trying to cache a realization for this brush because
  2033. // we have removed it from Hmgr and noone else has it locked down.
  2034. // We only have to do this if there is a cached realization and the
  2035. // brush is non-solid.
  2036. //
  2037. if ((pbp.pbr->crFore() != BO_NOTCACHED) &&
  2038. !pbp.pbr->bCachedIsSolid())
  2039. {
  2040. ASSERTGDI(pbp.pbr->ulRealization() != NULL,
  2041. "ERROR ulRealization() is NULL");
  2042. ((PRBRUSH)pbp.pbr->ulRealization())->vRemoveRef(
  2043. pbp.pbr->bIsEngine() ? RB_ENGINE : RB_DRIVER);
  2044. }
  2045. //
  2046. // Brush is DIB pattern ? if so we may need to free ICM DIBs
  2047. //
  2048. if (pbp.pbr->flAttrs() & BR_IS_DIB)
  2049. {
  2050. //
  2051. // Free cached color translated ICM DIBs.
  2052. //
  2053. pbp.pbr->vDeleteIcmDIBs();
  2054. }
  2055. FREEOBJ(pbp.pbr, BRUSH_TYPE);
  2056. //
  2057. // free pUser
  2058. //
  2059. if (!bCleanup && (pUser != (PBRUSHATTR)NULL))
  2060. {
  2061. HmgFreeObjectAttr((POBJECTATTR)pUser);
  2062. }
  2063. }
  2064. else
  2065. {
  2066. //
  2067. // Under Win31 deleting stock objects returns True.
  2068. //
  2069. BRUSHSELOBJ bo(hbrush);
  2070. if (!bo.bValid() || !bo.bIsGlobal())
  2071. bReturn = FALSE;
  2072. }
  2073. }
  2074. return(bReturn);
  2075. }
  2076. /******************************Public*Routine******************************\
  2077. * GreSetBrushGlobal
  2078. *
  2079. * Sets the brush to be a global one.
  2080. *
  2081. \**************************************************************************/
  2082. void
  2083. GreSetBrushGlobal(HBRUSH hbr)
  2084. {
  2085. BRUSHSELOBJ ebo(hbr);
  2086. if (ebo.bValid())
  2087. {
  2088. ebo.vGlobal();
  2089. }
  2090. }
  2091. /******************************Public*Routine******************************\
  2092. * GreMakeBrushStock
  2093. *
  2094. * Make the brush a stock brush.
  2095. *
  2096. \**************************************************************************/
  2097. HBRUSH
  2098. GreMakeBrushStock(HBRUSH hbr)
  2099. {
  2100. BRUSHSELOBJAPI ebo(hbr);
  2101. HANDLE bRet = 0;
  2102. BOOL bHandleModified = TRUE;
  2103. // Can make the brush a stock brush only when:
  2104. // (1) It is valid
  2105. // (2) Its not global already (i.e already stock)
  2106. // (3) Its not a DIBSection based brush.
  2107. // (4) Its not selected into any DC already.
  2108. if (!ebo.bValid() || ebo.bIsGlobal() || ebo.pbrush()->cShareLockGet() > 0)
  2109. {
  2110. STOCKWARNING("GreMakeBrushStock (%p) invalid/global/selected\n",hbr);
  2111. return (HBRUSH)0;
  2112. }
  2113. bRet = (HANDLE)((ULONG_PTR)hbr | GDISTOCKOBJ);
  2114. if (InterlockedDecrement(&gStockBrushFree) >= 0 &&
  2115. GreSetBrushOwner((HBRUSH)hbr,OBJECT_OWNER_PUBLIC) &&
  2116. (bHandleModified = HmgLockAndModifyHandleType((HOBJ)bRet)))
  2117. {
  2118. ebo.pbrush()->flAttrs(ebo.pbrush()->flAttrs() | BR_IS_GLOBAL);
  2119. return (HBRUSH)bRet;
  2120. }
  2121. else
  2122. {
  2123. if (!bHandleModified)
  2124. GreSetBrushOwner((HBRUSH)hbr,OBJECT_OWNER_CURRENT);
  2125. STOCKWARNING("GreMakeBrushStock (%p) Count/GreSetBrushOwner/ModifyH failed\n",bRet);
  2126. InterlockedIncrement(&gStockBrushFree);
  2127. bRet = 0;
  2128. }
  2129. return (HBRUSH)bRet;
  2130. }
  2131. /******************************Public*Routine******************************\
  2132. * GreMakeBrushNonStock
  2133. *
  2134. * Makes the brush a non stock brush
  2135. *
  2136. \**************************************************************************/
  2137. HBRUSH
  2138. GreMakeBrushNonStock(HBRUSH hbr)
  2139. {
  2140. HANDLE bRet = 0;
  2141. BRUSHSELOBJAPI ebo(hbr);
  2142. // Can make a stock brush non stock only when
  2143. // (1) It is valid
  2144. // (2) It is a global brush
  2145. // (3) It is not a Fixed stock brush
  2146. if (ebo.bValid() && ebo.bIsGlobal() && !ebo.pbrush()->bIsFixedStock())
  2147. {
  2148. bRet = (HANDLE)((ULONG_PTR)hbr & ~GDISTOCKOBJ);
  2149. if (ebo.pbrush()->cShareLockGet() > 0)
  2150. {
  2151. // The brush has more than one share lock. This means it will need
  2152. // to be lazy deleted.
  2153. ebo.pbrush()->vSetMakeNonStock();
  2154. STOCKINFO("GreMakeBrushNonStock (%p) is selected. Delay it\n", hbr);
  2155. }
  2156. else if(HmgLockAndModifyHandleType((HOBJ)bRet))
  2157. {
  2158. ebo.pbrush()->flAttrs(ebo.pbrush()->flAttrs() & ~BR_IS_GLOBAL);
  2159. if(!GreSetBrushOwner((HBRUSH)bRet,OBJECT_OWNER_CURRENT))
  2160. {
  2161. bRet = 0;
  2162. STOCKWARNING("GreMakeBrushNonStock (%p) GreSetBrushOwner failed\n", bRet);
  2163. }
  2164. else
  2165. {
  2166. InterlockedIncrement(&gStockBrushFree);
  2167. }
  2168. }
  2169. else
  2170. {
  2171. bRet = 0;
  2172. }
  2173. }
  2174. return (HBRUSH)bRet;
  2175. }
  2176. /******************************Public*Routine******************************\
  2177. * GreSetBrushOwner
  2178. *
  2179. * Sets the brush owner.
  2180. *
  2181. \**************************************************************************/
  2182. BOOL
  2183. GreSetBrushOwner(
  2184. HBRUSH hbr,
  2185. W32PID lPid
  2186. )
  2187. {
  2188. // If it is a global brush which by design are public we dont need to
  2189. // do anything.
  2190. {
  2191. BRUSHSELOBJ ebo(hbr);
  2192. if (ebo.bValid())
  2193. {
  2194. if (ebo.bIsGlobal())
  2195. return TRUE;
  2196. }
  2197. }
  2198. BOOL bStatus = FALSE;
  2199. PBRUSHATTR pBrushattr = NULL;
  2200. PENTRY pentry;
  2201. UINT uiIndex = (UINT) HmgIfromH(hbr);
  2202. if (uiIndex < gcMaxHmgr)
  2203. {
  2204. pentry = &gpentHmgr[uiIndex];
  2205. if (lPid == OBJECT_OWNER_CURRENT)
  2206. {
  2207. pBrushattr = (PBRUSHATTR)HmgAllocateObjectAttr();
  2208. }
  2209. //
  2210. // Accquire handle lock. Don't check PID here because owner could
  2211. // be NONE, not PUBLIC
  2212. //
  2213. HANDLELOCK HandleLock(pentry, FALSE);
  2214. if (HandleLock.bValid())
  2215. {
  2216. POBJ pobj = pentry->einfo.pobj;
  2217. if ((pentry->Objt == BRUSH_TYPE) && (pentry->FullUnique== HmgUfromH(hbr)))
  2218. {
  2219. PBRUSH pBrush = (PBRUSH)pobj;
  2220. if ((pobj->cExclusiveLock == 0) ||
  2221. (pobj->Tid == (PW32THREAD)PsGetCurrentThread()))
  2222. {
  2223. //
  2224. // Handle is locked. It is illegal to accquire the hmgr
  2225. // resource when a handle is locked.
  2226. //
  2227. if ((lPid == OBJECT_OWNER_NONE) ||
  2228. (lPid == OBJECT_OWNER_PUBLIC))
  2229. {
  2230. //
  2231. // free PBRUSHATTR if PID matches current process
  2232. // transfer brushattributes to kernel mode.
  2233. if (HandleLock.Pid() == W32GetCurrentPID())
  2234. {
  2235. //
  2236. // If user mode BRUSHATTR is allocated for this
  2237. // brush
  2238. //
  2239. if (pBrush->pBrushattr() != &pBrush->_Brushattr)
  2240. {
  2241. // Copy pBrushattr() to _BrushAttr
  2242. pBrush->_Brushattr = *(pBrush->pBrushattr());
  2243. // Free BRUSHATTR at bottom of function
  2244. pBrushattr = pBrush->pBrushattr();
  2245. // Set pBrushAttr to point to internal
  2246. pBrush->pBrushattr(&pBrush->_Brushattr);
  2247. // Clear entry
  2248. pentry->pUser = NULL;
  2249. }
  2250. // Set Brush owner to NONE or PUBLIC
  2251. HandleLock.Pid(lPid);
  2252. // dec process handle count
  2253. HmgDecProcessHandleCount(W32GetCurrentPID());
  2254. bStatus = TRUE;
  2255. }
  2256. else if (HandleLock.Pid() == OBJECT_OWNER_NONE)
  2257. {
  2258. // Allow to set from NONE to PUBLIC or NONE
  2259. HandleLock.Pid(lPid);
  2260. bStatus = TRUE;
  2261. }
  2262. //
  2263. // Move bitmap owner if needed. No need to do this if
  2264. // we are doing OBJECT_OWNER_NONE.
  2265. //
  2266. if (bStatus && lPid == OBJECT_OWNER_PUBLIC)
  2267. {
  2268. if (pBrush->hbmPattern() != (HBITMAP)NULL)
  2269. {
  2270. GreSetBitmapOwner(pBrush->hbmPattern(), OBJECT_OWNER_PUBLIC);
  2271. }
  2272. }
  2273. }
  2274. else if (lPid == OBJECT_OWNER_CURRENT)
  2275. {
  2276. //
  2277. // can only set to OBJECT_OWNER_CURRENT if Brush is
  2278. // not owned, or already owned by current pid.
  2279. //
  2280. lPid = W32GetCurrentPID();
  2281. if (HandleLock.Pid() == lPid ||
  2282. HandleLock.Pid() == OBJECT_OWNER_NONE ||
  2283. HandleLock.Pid() == OBJECT_OWNER_PUBLIC)
  2284. {
  2285. BOOL bIncHandleCount = FALSE;
  2286. bStatus = TRUE;
  2287. // only inc handle count if assigning new pid
  2288. if (HandleLock.Pid() != lPid)
  2289. {
  2290. // dont check quota for Brushes. ???
  2291. if (HmgIncProcessHandleCount(lPid,BRUSH_TYPE))
  2292. bIncHandleCount = TRUE;
  2293. }
  2294. //
  2295. // Check if user object already allocated for this
  2296. // handle
  2297. //
  2298. if (pentry->pUser == NULL)
  2299. {
  2300. if (pBrushattr != NULL)
  2301. {
  2302. // Set BrushAttr pointer
  2303. pBrush->pBrushattr(pBrushattr);
  2304. // Set pUser in ENTRY
  2305. pentry->pUser = pBrushattr;
  2306. // copy clean brush attrs
  2307. *pBrushattr = pBrush->_Brushattr;
  2308. // Set pBrushattr to NULL so it is not freed
  2309. pBrushattr = NULL;
  2310. }
  2311. else
  2312. {
  2313. WARNING("GreSetBrushOwner failed - No BRUSHATTR available");
  2314. bStatus = FALSE;
  2315. // reduce handle quota count
  2316. if (bIncHandleCount)
  2317. HmgDecProcessHandleCount(lPid);
  2318. }
  2319. }
  2320. if (bStatus)
  2321. {
  2322. // Set new owner
  2323. HandleLock.Pid(lPid);
  2324. //
  2325. // Move bitmap owner if needed.
  2326. //
  2327. if (pBrush->hbmPattern() != (HBITMAP)NULL)
  2328. {
  2329. GreSetBitmapOwner(pBrush->hbmPattern(), OBJECT_OWNER_CURRENT);
  2330. }
  2331. }
  2332. }
  2333. else
  2334. {
  2335. WARNING("GreSetBrushOwner failed, trying to set directly from one PID to another");
  2336. }
  2337. }
  2338. else
  2339. {
  2340. WARNING("GreSetBrushOwner failed, bad lPid");
  2341. }
  2342. }
  2343. else
  2344. {
  2345. WARNING("GreSetBrushOwner failed - Handle is exclusivly locked");
  2346. }
  2347. }
  2348. else
  2349. {
  2350. WARNING("GreSetBrushOwner failed - bad unique or object type");
  2351. }
  2352. HandleLock.vUnlock();
  2353. }
  2354. }
  2355. else
  2356. {
  2357. WARNING("GtreSetBrushOwner failed - invalid handle index\n");
  2358. }
  2359. // free pBrushattr if needed
  2360. if (pBrushattr)
  2361. {
  2362. HmgFreeObjectAttr((POBJECTATTR)pBrushattr);
  2363. }
  2364. return(bStatus);
  2365. }
  2366. /******************************Public*Routine******************************\
  2367. * vFreeOrCacheRbrush
  2368. *
  2369. * Either frees the current RBRUSH (the one pointed to by the this pointer) or
  2370. * puts it in the 1-deep RBRUSH cache, if the cache is empty.
  2371. *
  2372. * History:
  2373. *
  2374. * 30-Sep-1996 -by- Tom Zakrajsek [tomzak]
  2375. * Fixed it for multi brushes (DDML).
  2376. *
  2377. * 14-Dec-1993 -by- Michael Abrash [mikeab]
  2378. * Wrote it.
  2379. \**************************************************************************/
  2380. VOID MulDestroyBrushInternal(VOID*);
  2381. VOID RBRUSH::vFreeOrCacheRBrush(RBTYPE rbtype)
  2382. {
  2383. //
  2384. // If RBRUSH is for UMPD, just free it
  2385. //
  2386. if (!IS_SYSTEM_ADDRESS(this))
  2387. {
  2388. ASSERTGDI(bUMPDRBrush(),"RBRUSH::vFreeOrCacheRBrush UserMode brush does not have bUMPDBrush() bit on\n");
  2389. EngFreeUserMem(this);
  2390. return;
  2391. }
  2392. PRBRUSH *pprbrush;
  2393. // The bMultiBrush check is only valid for DRIVER realizations.
  2394. // Otherwise, it is assumed false.
  2395. BOOL bMulti = FALSE;
  2396. if (rbtype == RB_DRIVER)
  2397. {
  2398. pprbrush = &gpCachedDbrush;
  2399. bMulti = bMultiBrush();
  2400. if (bMulti)
  2401. {
  2402. PVOID pvRbrush = (PVOID)(((PDBRUSH)this)->aj);
  2403. MulDestroyBrushInternal(pvRbrush);
  2404. }
  2405. }
  2406. else
  2407. {
  2408. pprbrush = &gpCachedEngbrush;
  2409. }
  2410. // If there's already a cached RBRUSH, or this is a DDML brush
  2411. // just free this.
  2412. if ((*pprbrush != NULL) || (bMulti == TRUE))
  2413. {
  2414. VFREEMEM(this);
  2415. }
  2416. else
  2417. {
  2418. PRBRUSH pOldRbrush;
  2419. // There's no cached RBRUSH, and it's not a DDML brush,
  2420. // so cache this one.
  2421. if ((pOldRbrush = (PRBRUSH)
  2422. InterlockedExchangePointer((PVOID *)pprbrush, this))
  2423. != NULL)
  2424. {
  2425. // Before we could cache this one, someone else cached another one,
  2426. // which we just acquired responsibility for, so free it.
  2427. VFREEMEM(pOldRbrush);
  2428. }
  2429. }
  2430. }
  2431. /******************************Public*Routine******************************\
  2432. * BRUSH::hFindIcmDIB
  2433. *
  2434. * Search ICM DIBs associated with brush until a match is found
  2435. *
  2436. * Arguments:
  2437. *
  2438. * Return Value:
  2439. *
  2440. * History:
  2441. *
  2442. * 9/25/1996 Mark Enstrom [marke]
  2443. *
  2444. \**************************************************************************/
  2445. HBITMAP BRUSH::hFindIcmDIB(HANDLE hcmXform)
  2446. {
  2447. ICMMSG(("hFindIcmDIB: FIND ICM DIB \n"));
  2448. if (hcmXform == NULL)
  2449. {
  2450. return _hbmPattern;
  2451. }
  2452. else
  2453. {
  2454. GreAcquireFastMutex(ghfmMemory);
  2455. PICM_DIB_LIST pDIBList = pIcmDIBList();
  2456. while (pDIBList != NULL)
  2457. {
  2458. if (pDIBList->hcmXform == hcmXform)
  2459. {
  2460. GreReleaseFastMutex(ghfmMemory);
  2461. return(pDIBList->hDIB);
  2462. }
  2463. pDIBList = pDIBList->pNext;
  2464. }
  2465. GreReleaseFastMutex(ghfmMemory);
  2466. return(NULL);
  2467. }
  2468. }
  2469. BOOL BRUSH::bAddIcmDIB(HANDLE hcmXform,HBITMAP hDIB)
  2470. {
  2471. ICMMSG(("bAddIcmDIB: ADD ICM DIB \n"));
  2472. BOOL bRet = FALSE;
  2473. //
  2474. // Check current hcmform is not on the list.
  2475. //
  2476. if (hFindIcmDIB(hcmXform))
  2477. {
  2478. ICMMSG(("bAddIcmDIB(): The DIB for hcmXform is exist\n"));
  2479. //
  2480. // hcmXform is exist,
  2481. //
  2482. // Do we need to do delete existing one and insert new one ??
  2483. //
  2484. return (FALSE);
  2485. }
  2486. SURFREF SurfDIB((HSURF) hDIB);
  2487. if (SurfDIB.bValid())
  2488. {
  2489. PICM_DIB_LIST pDIBList = (PICM_DIB_LIST)PALLOCNOZ(sizeof(ICM_DIB_LIST),'ldbG');
  2490. if (pDIBList)
  2491. {
  2492. //
  2493. // Inc. ref. count
  2494. //
  2495. {
  2496. SURFACE *ps = SurfDIB.ps;
  2497. ps->vInc_cRef();
  2498. }
  2499. //
  2500. // Fill DIBList cell.
  2501. //
  2502. pDIBList->hcmXform = hcmXform;
  2503. pDIBList->hDIB = hDIB;
  2504. pDIBList->pNext = pIcmDIBList();
  2505. //
  2506. // Updates list.
  2507. //
  2508. GreAcquireFastMutex(ghfmMemory);
  2509. pIcmDIBList(pDIBList);
  2510. GreReleaseFastMutex(ghfmMemory);
  2511. bRet = TRUE;
  2512. }
  2513. else
  2514. {
  2515. bRet = FALSE;
  2516. }
  2517. }
  2518. return(bRet);
  2519. }
  2520. VOID BRUSH::vDeleteIcmDIBs(VOID)
  2521. {
  2522. ICMMSG(("vDeleteIcmDIBs: Free ICM DIB \n"));
  2523. PICM_DIB_LIST pDIBList = pIcmDIBList();
  2524. GreAcquireFastMutex(ghfmMemory);
  2525. while (pDIBList != NULL)
  2526. {
  2527. PICM_DIB_LIST pNext = pDIBList->pNext;
  2528. HSURF hSurf = (HSURF) pDIBList->hDIB;
  2529. BOOL bValidSurface = FALSE;
  2530. //
  2531. // Dec. ref count, before deleting
  2532. //
  2533. {
  2534. SURFREF SurfDIB(hSurf);
  2535. if (SurfDIB.bValid())
  2536. {
  2537. SURFACE *ps = SurfDIB.ps;
  2538. ps->vDec_cRef();
  2539. bValidSurface = TRUE;
  2540. }
  2541. }
  2542. if (bValidSurface)
  2543. {
  2544. //
  2545. // Delete ICM-ed DIB surface.
  2546. //
  2547. if (!bDeleteSurface((HSURF)pDIBList->hDIB))
  2548. {
  2549. ICMMSG(("vDeleteICMDIBs(): bDeleteSurface is failed\n"));
  2550. }
  2551. }
  2552. else
  2553. {
  2554. ICMMSG(("vDeleteICMDIBs(): Invalid surface\n"));
  2555. }
  2556. //
  2557. // free the cell.
  2558. //
  2559. VFREEMEM(pDIBList);
  2560. pDIBList = pNext;
  2561. }
  2562. GreReleaseFastMutex(ghfmMemory);
  2563. }