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.

1191 lines
36 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: brushddi.cxx
  3. *
  4. * This provides the call backs necesary for brush realization.
  5. *
  6. * Created: 25-Apr-1991 20:59:49
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. BOOL
  13. EngRealizeBrush(
  14. BRUSHOBJ *pbo,
  15. SURFOBJ *psoTarget,
  16. SURFOBJ *psoPattern,
  17. SURFOBJ *psoMask,
  18. XLATEOBJ *pxlo,
  19. ULONG iHatch
  20. );
  21. BOOL
  22. bGetRealizedBrush(
  23. BRUSH *pbrush,
  24. EBRUSHOBJ *pebo,
  25. PFN_DrvRealizeBrush pfnDrv
  26. );
  27. #if DBG
  28. ULONG dbrushalloc = 0, dbrushcachecheck = 0;
  29. ULONG dbrushcachegrabbed = 0, dbrushcachehit = 0;
  30. #endif
  31. /******************************Public*Routine******************************\
  32. * BRUSHOBJ_pvAllocRbrush
  33. *
  34. * Allocates memory for the driver's realization of a brush. This is always
  35. * called by the driver, never by the engine.
  36. *
  37. * History:
  38. * 25-Apr-1991 -by- Patrick Haluptzok patrickh
  39. * Wrote it.
  40. \**************************************************************************/
  41. PVOID
  42. BRUSHOBJ_pvAllocRbrush(
  43. BRUSHOBJ *pbo, ULONG cj
  44. )
  45. {
  46. ASSERTGDI(cj != 0, "ERROR GDI BRUSHOBJ_pvAllocRbrush cj = 0");
  47. ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF,
  48. "ERROR GDI BRUSHOBJ_pvAllocRbrush solid color brush passed in");
  49. DBRUSH *pdbrush;
  50. #if DBG
  51. dbrushalloc++;
  52. #endif
  53. //
  54. // If there's a cached DBRUSH, try to use it instead of allocating
  55. //
  56. if (gpCachedDbrush != NULL)
  57. {
  58. #if DBG
  59. dbrushcachecheck++;
  60. #endif
  61. //
  62. // Try to grab the cached DBRUSH
  63. //
  64. if ((pdbrush =
  65. (PDBRUSH) InterlockedExchangePointer((PVOID *)&gpCachedDbrush,
  66. NULL))
  67. != NULL)
  68. {
  69. #if DBG
  70. dbrushcachegrabbed++;
  71. #endif
  72. //
  73. // Got the cached DBRUSH; see if it's big enough
  74. //
  75. // Note: -4 because we define the realization buffer start as aj[0]
  76. //
  77. if (pdbrush->ulSizeGet() >= (sizeof(DBRUSH) - 4 + cj))
  78. {
  79. #if DBG
  80. dbrushcachehit++;
  81. #endif
  82. //
  83. // It's big enough, so we'll use it and we're done
  84. //
  85. return(pbo->pvRbrush = pdbrush->aj);
  86. }
  87. else
  88. {
  89. //
  90. // Not big enough; free it and do a normal allocation
  91. //
  92. VFREEMEM(pdbrush);
  93. }
  94. }
  95. }
  96. // Note: -4 because we define the realization buffer start as aj[0]
  97. if ((pdbrush = (DBRUSH *)PALLOCMEM(ULONGSIZE_T(sizeof(DBRUSH) - 4 + cj),'rbdG'))
  98. != NULL)
  99. {
  100. //
  101. // Remember the size of the allocation, for caching.
  102. //
  103. pdbrush->ulSizeSet(sizeof(DBRUSH) - 4 + cj);
  104. return(pbo->pvRbrush = pdbrush->aj);
  105. }
  106. else
  107. {
  108. WARNING("Failed memory alloc BRUSHOBJ_pvAllocRbrush\n");
  109. return(NULL);
  110. }
  111. }
  112. //
  113. // User mode printer driver support
  114. //
  115. PVOID
  116. BRUSHOBJ_pvAllocRbrushUMPD(
  117. BRUSHOBJ *pbo,
  118. ULONG cj
  119. )
  120. {
  121. if (pbo->pvRbrush == NULL)
  122. {
  123. DBRUSH *pdbrush;
  124. cj += MAGIC_DBR_DIFF;
  125. if (pdbrush = (DBRUSH *) EngAllocUserMem(cj, UMPD_MEMORY_TAG))
  126. {
  127. pdbrush->ulSizeSet(cj);
  128. pdbrush->bMultiBrush(FALSE);
  129. pdbrush->bUMPDRBrush(TRUE);
  130. pbo->pvRbrush = pdbrush->aj;
  131. }
  132. }
  133. else
  134. {
  135. RIP("BRUSHOBJ_pvAllocRbrush when pvRbrush is not NULL\n");
  136. }
  137. return pbo->pvRbrush;
  138. }
  139. /******************************Public*Routine******************************\
  140. * vTryToCacheRealization
  141. *
  142. * Attempt to cache the realization pointed to by pdbrush and described by pebo
  143. * in the logical brush pointed to by pbrush. The way this works is that only
  144. * the first realization of the logical brush can be cached. crFore is the key
  145. * that indicates when the cached realization is valid. If crFore is not -1 when
  146. * the logical brush is being realized, we just go realize the brush; if it's
  147. * not -1, we check the cache ID fields to see if we can use the cached fields.
  148. * InterlockedExchange() is used below to set crFore to make sure the cache ID
  149. * fields are set before crFore. bCacheGrabbed() is used to protect the setting
  150. * of the cache ID fields; once it's set, no one else can modify the cache ID
  151. * fields, but no one else will try to use them until crFore is not -1.
  152. *
  153. * Also initializes the reference count in the realization to indicates either
  154. * 1 or 2 current uses, depending on whether caching took place.
  155. *
  156. * History:
  157. * 31-Oct-1993 -by- Michael Abrash [mikeab]
  158. * Wrote it.
  159. \**************************************************************************/
  160. VOID
  161. vTryToCacheRealization(
  162. EBRUSHOBJ *pebo,
  163. PRBRUSH prbrush,
  164. PBRUSH pbrush,
  165. BOOL bType
  166. )
  167. {
  168. // Reference count the realization once for being selected into this DC. This
  169. // assumes we won't succeed in caching the brush next; if we do, we do a double
  170. // reference count, once for caching in the logical brush and once for
  171. // selecting into the DC
  172. prbrush->cRef(1);
  173. // See if we can cache this realization in the logical brush; we can't if
  174. // another realization has already been cached in the logical brush
  175. if ( !pbrush->bCacheGrabbed() )
  176. {
  177. // Try to grab the "can cache" flag; if we don't get it, someone just
  178. // sneaked in and got it ahead of us, so we're out of luck and can't cache
  179. if ( pbrush->bGrabCache() )
  180. {
  181. // We got the "can cache" flag, so now we can cache this realization
  182. // in the logical brush
  183. // It's cached in the brush, so it won't be deleted until the logical
  184. // brush goes away and it's not selected into any DCs, so reference
  185. // count the realization again. We don't need to do an
  186. // InterlockedIncrement here because until crFore is set, no one else
  187. // can get at this realization. InterlockedExchange() is used below to
  188. // set crFore to make sure the reference count is set before anyone
  189. // else can see the caching info
  190. prbrush->cRef(2);
  191. // These cache ID fields must be set before crFore, because crFore
  192. // is the key that indicates when the cached realization is valid.
  193. // If crFore is -1 when the logical brush is being realized, we
  194. // just go realize the brush; if it's not -1, we check the cache ID
  195. // fields to see if we can use the cached fields.
  196. // InterlockedExchange() is used below to set crFore to make sure
  197. // the cache ID fields are set before crFore
  198. if (bType == CR_ENGINE_REALIZATION)
  199. {
  200. pbrush->SetEngineRealization();
  201. }
  202. else
  203. {
  204. pbrush->SetDriverRealization();
  205. }
  206. pbrush->crBack(pebo->crCurrentBack());
  207. pbrush->ulPalTime(pebo->ulDCPalTime());
  208. pbrush->ulSurfTime(pebo->ulSurfPalTime());
  209. pbrush->ulRealization((ULONG_PTR)prbrush);
  210. pbrush->hdevRealization(pebo->psoTarg()->hdev());
  211. pbrush->crPalColor(pebo->crDCPalColor());
  212. // This must be set last, because once it's set, other selections of
  213. // this logical brush will attempt to use the cached brush. The use of
  214. // InterlockedExchange in this method enforces this
  215. pbrush->crForeLocked(pebo->crCurrentText());
  216. // The realization is now cached in the logical brush
  217. }
  218. }
  219. }
  220. /******************************Public*Routine******************************\
  221. * BRUSHOBJ_pvGetRbrush
  222. *
  223. * Returns a pointer to the driver's realization of the brush.
  224. *
  225. * History:
  226. * 31-Oct-1993 -by- Michael Abrash
  227. * Rewrote to cache the first realization in the logical brush.
  228. *
  229. * 8-Sep-1992 -by- Paul Butzi
  230. * Rewrote it.
  231. *
  232. * Wed 05-Jun-1991 -by- Patrick Haluptzok [patrickh]
  233. * major revision
  234. *
  235. * 25-Apr-1991 -by- Patrick Haluptzok patrickh
  236. * Wrote it.
  237. \**************************************************************************/
  238. PVOID
  239. BRUSHOBJ_pvGetRbrush(
  240. BRUSHOBJ *pbo
  241. )
  242. {
  243. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  244. ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
  245. //
  246. // Check if the brush has already been realized.
  247. //
  248. if (pebo->pvRbrush != NULL)
  249. {
  250. return(pebo->pvRbrush);
  251. }
  252. //
  253. // Get this thing realized.
  254. //
  255. PDEVOBJ pdo(pebo->psoTarg()->hdev());
  256. if (!bGetRealizedBrush(pebo->pbrush(), pebo, PPFNDRV(pdo, RealizeBrush)))
  257. {
  258. if (pebo->pvRbrush != NULL)
  259. {
  260. VFREEMEM(DBRUSHSTART(pebo->pvRbrush)); // free the DBRUSH
  261. pebo->pvRbrush = NULL; // mark that there's no realization
  262. }
  263. return(NULL);
  264. }
  265. //
  266. // Try to cache the realization in the logical brush
  267. //
  268. //Make sure the brush is indeed realized
  269. if (pebo->pvRbrush == NULL)
  270. return(NULL);
  271. vTryToCacheRealization(pebo,
  272. (PDBRUSH) DBRUSHSTART(pebo->pvRbrush),
  273. pebo->pbrush(),
  274. CR_DRIVER_REALIZATION);
  275. return pebo->pvRbrush;
  276. }
  277. //
  278. // User mode printer driver support
  279. //
  280. PVOID
  281. BRUSHOBJ_pvGetRbrushUMPD(
  282. BRUSHOBJ *pbo
  283. )
  284. {
  285. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  286. if (pbo->iSolidColor != 0xFFFFFFFF)
  287. {
  288. RIP("BRUSHOBJ_pvGetRbrush called for solid brush\n");
  289. return NULL;
  290. }
  291. //
  292. // Check if the brush has already been realized
  293. //
  294. if (pebo->pvRbrush != NULL)
  295. return pebo->pvRbrush;
  296. //
  297. // Realize the brush
  298. //
  299. PDEVOBJ pdo(pebo->psoTarg()->hdev());
  300. if (!bGetRealizedBrush(pebo->pbrush(), pebo, PPFNDRV(pdo, RealizeBrush)))
  301. {
  302. if (pebo->pvRbrush != NULL)
  303. {
  304. EngFreeUserMem(DBRUSHSTART(pebo->pvRbrush));
  305. pebo->pvRbrush = NULL;
  306. }
  307. return NULL;
  308. }
  309. //Make sure the brush is indeed realized
  310. if (pebo->pvRbrush == NULL)
  311. return(NULL);
  312. #if defined(_WIN64)
  313. //
  314. // if we are doing WOW64 printing, skip the caching.
  315. //
  316. PW32THREAD pThread = W32GetCurrentThread();
  317. if (pThread->pClientID == NULL)
  318. #endif
  319. {
  320. // Try to cache the realization in the logical brush
  321. vTryToCacheRealization(pebo, (PDBRUSH)DBRUSHSTART(pebo->pvRbrush),
  322. pebo->pbrush(), CR_DRIVER_REALIZATION);
  323. }
  324. return pebo->pvRbrush;
  325. }
  326. /******************************Public*Routine******************************\
  327. * BRUSHOBJ_ulGetBrushColor
  328. *
  329. * Returns the RGB color for a solid brush.
  330. *
  331. * Oct-18-1995 -by- Lingyun Wang
  332. * Wrote it.
  333. \**************************************************************************/
  334. ULONG
  335. BRUSHOBJ_ulGetBrushColor(
  336. BRUSHOBJ *pbo
  337. )
  338. {
  339. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  340. if (pebo->bIsSolid())
  341. {
  342. if(pebo->flColorType & BR_ORIGCOLOR)
  343. {
  344. pebo->flColorType &= ~BR_ORIGCOLOR;
  345. return ((ULONG)(pebo->crOrignal()));
  346. }
  347. else
  348. {
  349. return ((ULONG)(pebo->crRealized()));
  350. }
  351. }
  352. else
  353. {
  354. return (ULONG)(-1);
  355. }
  356. }
  357. /******************************Public*Routine******************************\
  358. * BRUSHOBJ_hGetColorTransform
  359. *
  360. * Retuens the color transform for a brush.
  361. *
  362. * Feb-14-1997 -by- Hideyuki Nagase
  363. * Wrote it.
  364. ***************************************************************************/
  365. HANDLE
  366. BRUSHOBJ_hGetColorTransform(
  367. BRUSHOBJ *pbo
  368. )
  369. {
  370. ICMAPI(("BRUSHOBJ_hGetColorTransform()\n"));
  371. if (pbo == NULL)
  372. {
  373. WARNING("BRUSHOBJ_hGetColorTransform() BRUSHOBJ is NULL\n");
  374. return(NULL);
  375. }
  376. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  377. //
  378. // if ICM is not enabled for this. Or if ICM is done by host,
  379. // Color transform handle is for host ICM it is no meanings
  380. // for device driver. then just return NULL.
  381. //
  382. if (pebo->bIsDeviceICM())
  383. {
  384. if (pebo->hcmXform())
  385. {
  386. COLORTRANSFORMOBJ CXFormObj(pebo->hcmXform());
  387. if (CXFormObj.bValid())
  388. {
  389. return(CXFormObj.hGetDeviceColorTransform());
  390. }
  391. ICMMSG(("BRUSHOBJ_hGetColorTransform() COLORTRANSFORMOBJ is invalid\n"));
  392. }
  393. else
  394. {
  395. ICMMSG(("BRUSHOBJ_hGetColorTransform() Ident. color transform\n"));
  396. }
  397. }
  398. else
  399. {
  400. ICMMSG(("BRUSHOBJ_hGetColorTransform() ICM on device is not enabled\n"));
  401. }
  402. return(NULL);
  403. }
  404. /******************************Public*Routine******************************\
  405. * pvGetEngRbrush
  406. *
  407. * Returns: A pointer to the engines's realization of a logical brush.
  408. *
  409. * Only the engine calls this, it is not exported.
  410. *
  411. * History:
  412. * 31-Oct-1993 -by- Michael Abrash
  413. * Rewrote to cache the first realization in the logical brush.
  414. *
  415. * 8-Sep-1992 -by- Paul Butzi
  416. * Rewrote it.
  417. *
  418. * Wed 05-Jun-1991 -by- Patrick Haluptzok [patrickh]
  419. * major revision
  420. *
  421. * 25-Apr-1991 -by- Patrick Haluptzok patrickh
  422. * Wrote it - First pass.
  423. \**************************************************************************/
  424. PVOID
  425. pvGetEngRbrush(
  426. BRUSHOBJ *pbo
  427. )
  428. {
  429. EBRUSHOBJ *pebo = (EBRUSHOBJ *) pbo;
  430. ASSERTGDI(pbo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
  431. // Check if the brush has already been realized.
  432. if (pebo->pengbrush() != (PVOID) NULL)
  433. {
  434. return pebo->pengbrush();
  435. }
  436. // Get this thing realized.
  437. PDEVOBJ pdo(pebo->psoTarg()->hdev());
  438. if (!bGetRealizedBrush(pebo->pbrush(), pebo, EngRealizeBrush))
  439. {
  440. if (pebo->pengbrush() != NULL)
  441. {
  442. VFREEMEM(pebo->pengbrush()); // free the DBRUSH
  443. pebo->pengbrush(NULL); // mark that there's no realization
  444. }
  445. return(NULL);
  446. }
  447. // Try to cache the realization in the logical brush
  448. vTryToCacheRealization(pebo, pebo->pengbrush(), pebo->pbrush(),
  449. CR_ENGINE_REALIZATION);
  450. return(pebo->pengbrush());
  451. }
  452. /******************************Public*Routine******************************\
  453. * bGetRealizedBrush
  454. *
  455. * Returns: Pointer to a Realized brush.
  456. *
  457. * NOTE: The surface in pebo->psoTarg() is the surface of the original
  458. * destination of the drawing call. If a display driver was called,
  459. * but it punts by calling back to the engine with an engine-managed
  460. * bitmap it created, psoTarg() will still point to the original
  461. * display surface, not the DIB surface. The surface will have the
  462. * same hdev, iFormat, etc., but this means that the iType will be
  463. * wrong, so don't reference it! (EngRealizeBrush actually accounts
  464. * for this little lie.)
  465. *
  466. * History:
  467. * 14-Jul-1992 -by- Eric Kutter [erick]
  468. * added exception handling, changed from VOID to BOOL
  469. *
  470. * Mon 07-Oct-1991 -by- Patrick Haluptzok [patrickh]
  471. * add support for DIB_PAL_COLORS flag.
  472. *
  473. * 04-Jun-1991 -by- Patrick Haluptzok patrickh
  474. * Wrote it.
  475. \**************************************************************************/
  476. BOOL
  477. bGetRealizedBrush(
  478. BRUSH *pbrush,
  479. EBRUSHOBJ *pebo,
  480. PFN_DrvRealizeBrush pfnDrv
  481. )
  482. {
  483. ASSERTGDI(pebo->iSolidColor == 0xFFFFFFFF, "ERROR GDI iSolidColor");
  484. ASSERTGDI(pfnDrv != (PFN_DrvRealizeBrush) 0, "ERROR pfnDrv");
  485. //
  486. // quick out if it is a NULL brush
  487. //
  488. if (pbrush->ulStyle() == HS_NULL)
  489. {
  490. WARNING1("You are doing output calls with a NULL brush\n");
  491. return(FALSE);
  492. }
  493. //
  494. // Dispatch off to driver to get brush realized.
  495. //
  496. ULONG ulStyle = pbrush->ulStyle();
  497. SURFOBJ *psoPattern;
  498. SURFOBJ *psoMask = NULL;
  499. XEPALOBJ palSrc;
  500. XEPALOBJ palDest;
  501. SURFREF SurfBmoPattern;
  502. EXLATEOBJ exlo;
  503. XLATE *pxlo = NULL;
  504. SURFMEM SurfDimo;
  505. //
  506. // We default to this.
  507. //
  508. PDEVOBJ po(pebo->psoTarg()->hdev());
  509. ASSERTGDI(po.bValid(), "ERROR BRUSHOBJ_ 5");
  510. //
  511. // We need to hold the Devlock to protect against dynamic mode changes
  512. // while we muck around in the driver. If we're being call by the
  513. // driver, we're guaranteed to already be holding it, so we only have
  514. // to do this if we're being called by GDI's Eng functions.
  515. //
  516. DEVLOCKOBJ dlo;
  517. if (pfnDrv == EngRealizeBrush)
  518. {
  519. dlo.vLock(po);
  520. }
  521. else
  522. {
  523. dlo.vInit();
  524. }
  525. if (pbrush->ulStyle() < HS_DDI_MAX)
  526. {
  527. //
  528. // For hatch brushes, the pattern is also the mask
  529. //
  530. SurfBmoPattern.vAltLock((HSURF)po.hbmPattern(pbrush->ulStyle()));
  531. psoMask = SurfBmoPattern.pSurfobj();
  532. if (exlo.pCreateXlateObject(2))
  533. {
  534. ULONG ulValue1, ulValue2;
  535. if (pebo->bIsCMYKColor())
  536. {
  537. //
  538. // We are in CMYK color context, we just set CMYK color
  539. //
  540. ulValue1 = pebo->crCurrentBack();
  541. ulValue2 = pebo->crRealized();
  542. exlo.pxlo()->vSetIndex(0, ulValue1);
  543. exlo.pxlo()->vSetIndex(1, ulValue2);
  544. pxlo = exlo.pxlo();
  545. pxlo->vCheckForICM(pebo->hcmXform(),pebo->lIcmMode());
  546. pxlo->ppalSrc = ppalMono;
  547. pxlo->ppalDst = pebo->palSurf().ppalGet();
  548. pxlo->ppalDstDC = pebo->palDC().ppalGet();
  549. }
  550. else
  551. {
  552. ulValue1 = ulGetNearestIndexFromColorref(
  553. pebo->palSurf(),
  554. pebo->palDC(),
  555. pebo->crCurrentBack()
  556. );
  557. ulValue2 = ulGetNearestIndexFromColorref(
  558. pebo->palSurf(),
  559. pebo->palDC(),
  560. pebo->crRealized()
  561. );
  562. //
  563. // Windows compability issue:
  564. // force to draw on the background
  565. //
  566. // We force the forground to be mapped
  567. // to an index opposite to the background
  568. //
  569. if ((pebo->psoTarg()->iFormat() == BMF_1BPP) &&
  570. (pebo->palSurf().bIsIndexed()) &&
  571. (pebo->crCurrentBack() != pebo->crRealized()) &&
  572. (ulValue1 == ulValue2))
  573. {
  574. ulValue2 = 1-ulValue1;
  575. }
  576. exlo.pxlo()->vSetIndex(0, ulValue1);
  577. exlo.pxlo()->vSetIndex(1, ulValue2);
  578. pxlo = exlo.pxlo();
  579. pxlo->vCheckForICM(pebo->hcmXform(),pebo->lIcmMode());
  580. pxlo->vCheckForTrivial();
  581. pxlo->ppalSrc = ppalMono;
  582. pxlo->ppalDst = pebo->palSurf().ppalGet();
  583. pxlo->ppalDstDC = pebo->palDC().ppalGet();
  584. }
  585. pxlo->iForeDst = ulValue1;
  586. pxlo->iBackDst = ulValue2;
  587. pxlo->flPrivate |= XLATE_FROM_MONO;
  588. }
  589. else
  590. {
  591. WARNING("ERROR failed to create hatch xlate\n");
  592. return(FALSE);
  593. }
  594. }
  595. else if (pbrush->ulStyle() < HS_NULL)
  596. {
  597. //
  598. // For solid brushes.
  599. //
  600. ASSERTGDI(pbrush->flAttrs() & BR_IS_SOLID, "ERROR non-solid brush");
  601. ASSERTGDI((pbrush->flAttrs() & BR_DITHER_OK) ||
  602. (po.bCapsForceDither()),
  603. "ERROR BRUSHOBJ_ 1");
  604. //
  605. // We will not dither CMYK color brush. Driver should not call BRUSHOBJ_pvGetRbrush
  606. // with CMYK solid color brush.
  607. //
  608. if (pebo->bIsCMYKColor())
  609. {
  610. WARNING("ERROR bGetRealizedBrush() Can't dither CMYK color brush\n");
  611. return (FALSE);
  612. }
  613. //
  614. // This means they want us to dither the color and nothing
  615. // in their palette is close enough that we can't just use
  616. // a solid color.
  617. //
  618. if (pebo->crRealized() & 0x01000000)
  619. {
  620. pebo->crRealized(rgbFromColorref(pebo->palSurf(),
  621. pebo->palDC(),
  622. pebo->crRealized()));
  623. }
  624. //
  625. // Use the nifty DitherOnRealize option, if the driver supports it and
  626. // we're not realizing the brush on behalf of the engine simulations
  627. // (since the engine will be drawing, it will need its own realization,
  628. // not the driver's):
  629. //
  630. if ((po.flGraphicsCaps() & GCAPS_DITHERONREALIZE) &&
  631. (pfnDrv != EngRealizeBrush))
  632. {
  633. if ((*pfnDrv) (pebo,
  634. pebo->psoTarg()->pSurfobj(),
  635. (SURFOBJ *) NULL,
  636. (SURFOBJ *) NULL,
  637. NULL,
  638. pebo->crRealized() | RB_DITHERCOLOR))
  639. {
  640. return(TRUE);
  641. }
  642. }
  643. DEVBITMAPINFO dbmi;
  644. if (pebo->psoTarg()->iFormat() == BMF_1BPP)
  645. {
  646. dbmi.iFormat = BMF_1BPP;
  647. }
  648. else
  649. {
  650. dbmi.iFormat = po.iDitherFormat();
  651. }
  652. dbmi.cxBitmap = po.cxDither();
  653. dbmi.cyBitmap = po.cyDither();
  654. dbmi.hpal = 0;
  655. dbmi.fl = BMF_TOPDOWN;
  656. if (!SurfDimo.bCreateDIB(&dbmi, NULL))
  657. {
  658. WARNING("Failed memory alloc in dither brush\n");
  659. return(FALSE);
  660. }
  661. ULONG iRes;
  662. ULONG iDitherMode = ((pebo->psoTarg()->iFormat() == BMF_1BPP) ? DM_MONOCHROME: DM_DEFAULT);
  663. if (PPFNVALID(po, DitherColor))
  664. {
  665. iRes = (*PPFNDRV(po, DitherColor)) (
  666. po.bUMPD() ? (DHPDEV)po.ppdev : po.dhpdev(),
  667. iDitherMode,
  668. pebo->crRealized(),
  669. (PULONG) SurfDimo.ps->pvBits());
  670. }
  671. else
  672. {
  673. iRes = EngDitherColor(po.hdev(),
  674. iDitherMode,
  675. pebo->crRealized(),
  676. (PULONG) SurfDimo.ps->pvBits());
  677. }
  678. switch (iRes)
  679. {
  680. case DCR_DRIVER:
  681. pxlo = &xloIdent;
  682. break;
  683. case DCR_HALFTONE:
  684. {
  685. if ((po.pDevHTInfo() == NULL) && !po.bEnableHalftone(NULL))
  686. return(FALSE);
  687. DEVICEHALFTONEINFO *pDevHTInfo = (DEVICEHALFTONEINFO *)po.pDevHTInfo();
  688. COLORTRIAD ColorTriad;
  689. CHBINFO CHBInfo;
  690. COLORREF cr = pebo->crRealized();
  691. ColorTriad.Type = COLOR_TYPE_RGB;
  692. ColorTriad.BytesPerPrimary = sizeof(BYTE);
  693. ColorTriad.BytesPerEntry = sizeof(DWORD);
  694. ColorTriad.PrimaryOrder = PRIMARY_ORDER_RGB;
  695. ColorTriad.PrimaryValueMax = 255;
  696. ColorTriad.ColorTableEntries = 1;
  697. ColorTriad.pColorTable = (LPVOID)&cr;
  698. CHBInfo.Flags = (BYTE)((po.GdiInfo()->flHTFlags & HT_FLAG_OUTPUT_CMY) ?
  699. 0 : CHBF_USE_ADDITIVE_PRIMS);
  700. // Control ICM bits for halftoning
  701. if ((pebo->bIsAppsICM()) ||
  702. (!pebo->bDeviceCalibrate() && (pebo->bIsHostICM() || pebo->bIsDeviceICM())))
  703. {
  704. ICMDUMP(("bGetRealizedBrush(): ICM with Halftone (Dynamic Bit On)\n"));
  705. // Some kind of ICM (ICM on Application, Graphics Engine or Device)
  706. // is enabled, so tell halftoning code to disable thier color adjustment.
  707. CHBInfo.Flags |= CHBF_ICM_ON;
  708. }
  709. else
  710. {
  711. ICMDUMP(("bGetRealizedBrush(): ICM with Halftone (Dynamic Bit Off)\n"));
  712. }
  713. if ((pDevHTInfo->cxPattern != dbmi.cxBitmap) ||
  714. (pDevHTInfo->cyPattern != dbmi.cyBitmap))
  715. {
  716. SurfDimo.ps->bDeleteSurface();
  717. dbmi.cxBitmap = pDevHTInfo->cxPattern;
  718. dbmi.cyBitmap = pDevHTInfo->cyPattern;
  719. if (!SurfDimo.bCreateDIB(&dbmi, NULL))
  720. {
  721. WARNING("Failed memory alloc in dither brush1\n");
  722. return(FALSE);
  723. }
  724. }
  725. switch(po.GdiInfo()->ulHTOutputFormat)
  726. {
  727. case HT_FORMAT_1BPP:
  728. CHBInfo.DestSurfaceFormat = (BYTE)BMF_1BPP;
  729. break;
  730. case HT_FORMAT_4BPP:
  731. CHBInfo.DestSurfaceFormat = (BYTE)BMF_4BPP;
  732. break;
  733. case HT_FORMAT_4BPP_IRGB:
  734. CHBInfo.DestSurfaceFormat = (BYTE)BMF_4BPP_VGA16;
  735. break;
  736. case HT_FORMAT_8BPP:
  737. CHBInfo.DestSurfaceFormat = (BYTE)BMF_8BPP_VGA256;
  738. break;
  739. case HT_FORMAT_16BPP:
  740. //
  741. // Need to switch between BMF_16BPP_555 and BMF_16BPP_565
  742. //
  743. CHBInfo.DestSurfaceFormat = (BYTE)BMF_16BPP_555;
  744. break;
  745. case HT_FORMAT_32BPP:
  746. CHBInfo.DestSurfaceFormat = (BYTE)BMF_32BPP;
  747. break;
  748. default:
  749. WARNING("Halftone format not supported\n");
  750. return(FALSE);
  751. }
  752. CHBInfo.DestScanLineAlignBytes = BMF_ALIGN_DWORD;
  753. CHBInfo.DestPrimaryOrder = (BYTE)po.GdiInfo()->ulPrimaryOrder;
  754. // Brushes, unlike scanned in images, have linear RGB gamma.
  755. // Use a gamma value of 1 can produce lighter, closer to wfw halftone
  756. // images for solid brushes. This is to fix powerpnt shaded background
  757. // printing. Other apps that print black text on dark background will
  758. // benefit from this fix as well.
  759. COLORADJUSTMENT ca = *pebo->pColorAdjustment();
  760. ca.caRedGamma = 10000;
  761. ca.caGreenGamma = 10000;
  762. ca.caBlueGamma = 10000;
  763. if (HT_CreateHalftoneBrush(
  764. pDevHTInfo,
  765. (PHTCOLORADJUSTMENT)&ca,
  766. &ColorTriad,
  767. CHBInfo,
  768. (PULONG)SurfDimo.ps->pvBits()) > 0)
  769. {
  770. // Set up the translate object.
  771. if (po.bHTPalIsDevPal())
  772. {
  773. pxlo = &xloIdent;
  774. }
  775. else
  776. {
  777. EPALOBJ palHT((HPALETTE)pDevHTInfo->DeviceOwnData);
  778. palDest.ppalSet(pebo->psoTarg()->ppal());
  779. if (!exlo.bInitXlateObj(
  780. pebo->hcmXform(),
  781. pebo->lIcmMode(),
  782. palHT, palDest,
  783. pebo->palDC(),
  784. pebo->palDC(),
  785. pebo->crCurrentText(),
  786. pebo->crCurrentBack(),
  787. 0x00FFFFFF
  788. ))
  789. {
  790. WARNING("Failed to create an xlate bGetRealizedBrush DIB_PAL_COLORS\n");
  791. return(FALSE);
  792. }
  793. pxlo = exlo.pxlo();
  794. }
  795. break;
  796. }
  797. } // case DCR_HALFTONE
  798. default:
  799. WARNING("DrvDitherColor returned invalid value or failed\n");
  800. return(FALSE);
  801. } // switch (iRes)
  802. }
  803. else // if (pbrush->ulStyle() >= HS_NULL)
  804. {
  805. BOOL bIcmBrush = FALSE;
  806. //
  807. // For bitmap/pattern brushes.
  808. //
  809. HSURF hDIB = (HSURF)pbrush->hbmPattern();
  810. ASSERTGDI(pbrush->ulStyle() <= HS_PATMSK, "ERROR ulStyle is bad");
  811. // ICM is enabled ? and the Brush is DIB ? For Device Depend Bitmap, we will
  812. // not enable ICM. Only for DIB.
  813. if (pebo->bIsHostICM())
  814. {
  815. if (pebo->hcmXform() != NULL)
  816. {
  817. if (pbrush->flAttrs() & BR_IS_DIB)
  818. {
  819. // if ICM is enabled, the BRUSHOBJ should have color transform.
  820. if (pbrush->iUsage() == DIB_RGB_COLORS)
  821. {
  822. ICMMSG(("bGetRealizedBrush: TRY Find ICM DIB\n"));
  823. // Find color translated brush DIB.
  824. HSURF hIcmDIB = (HSURF)(pbrush->hFindIcmDIB(pebo->hcmXform()));
  825. if (hIcmDIB == NULL)
  826. {
  827. // Somehow, we could not find DIB, just use orginal.
  828. WARNING1("bGetRealizedBrush(): hFindIcmDIB() returns NULL\n");
  829. }
  830. else
  831. {
  832. // Replace DIB handle with ICM-ed DIB.
  833. hDIB = hIcmDIB;
  834. bIcmBrush = TRUE;
  835. }
  836. }
  837. else
  838. {
  839. // if DIB is other than DIB_RGB_COLORS, ICM DIB will not be used.
  840. ICMMSG(("bGetRealizedBrush(): Brush color is not DIB_RGB_COLORS\n"));
  841. }
  842. }
  843. else if (pbrush->flAttrs() & BR_IS_MONOCHROME)
  844. {
  845. ICMMSG(("bGetRealizedBrush(): Brush color is BR_IS_MONOCHROME\n"));
  846. bIcmBrush = TRUE;
  847. }
  848. }
  849. else
  850. {
  851. // ICM is enabled, but no color transform, it means identical color transform
  852. // so, there is no ICM-ed DIB.
  853. ICMMSG(("bGetRealizedBrush(): Color transform is identical\n"));
  854. // If we are in CMYK mode, we must have color transform.
  855. if (!pebo->bIsCMYKColor())
  856. {
  857. bIcmBrush = TRUE;
  858. }
  859. }
  860. }
  861. else if (pebo->bIsAppsICM() || pebo->bIsDeviceICM())
  862. {
  863. bIcmBrush = TRUE;
  864. }
  865. SurfBmoPattern.vAltLock(hDIB);
  866. if(!SurfBmoPattern.bValid())
  867. {
  868. WARNING("WARNING:bGetRealizedBrush(): Invalid SurfBmopattern\n");
  869. return(FALSE);
  870. }
  871. palSrc.ppalSet(SurfBmoPattern.ps->ppal());
  872. palDest.ppalSet(pebo->psoTarg()->ppal());
  873. if (pbrush->bPalColors())
  874. {
  875. ASSERTGDI(palSrc.bValid(), "ERROR3invalid hpal pvGetEngRbrush\n");
  876. if (!exlo.bMakeXlate((PUSHORT) palSrc.apalColorGet(),
  877. pebo->palDC(),
  878. pebo->psoTarg(),
  879. palSrc.cColorTableLength(),
  880. palSrc.cEntries()))
  881. {
  882. WARNING("Failed to create an xlate bGetRealizedBrush DIB_PAL_COLORS\n");
  883. return(FALSE);
  884. }
  885. pxlo = exlo.pxlo();
  886. }
  887. else if (pbrush->bPalIndices())
  888. {
  889. if (SurfBmoPattern.ps->iFormat() != pebo->psoTarg()->iFormat())
  890. {
  891. WARNING("Output failed: DIB_PAL_INDICES brush not compatible with dest surface\n");
  892. return(FALSE);
  893. }
  894. pxlo = &xloIdent;
  895. }
  896. else
  897. {
  898. // With our wonderful API we can't fail a brush selection like Windows would.
  899. // Instead we let the app think he selected the bitmap brush in and then at
  900. // realize time if that wasn't a valid selection we fail the realize. Good
  901. // luck writing new apps.
  902. PPALETTE ppalSrcTmp;
  903. // We need to make sure this could be selected into this DC. If it is a device
  904. // managed bitmap, it must be the same device.
  905. if ((
  906. (SurfBmoPattern.ps->iType() != STYPE_BITMAP) ||
  907. (SurfBmoPattern.ps->dhsurf() != 0)
  908. )
  909. &&
  910. (SurfBmoPattern.ps->hdev() != po.hdev()))
  911. {
  912. WARNING1("bGetRealizedBrush failed Device surface for another PDEV\n");
  913. return (FALSE);
  914. }
  915. else if (SurfBmoPattern.ps->ppal() != NULL)
  916. {
  917. // No problem, we already have color information.
  918. ppalSrcTmp = SurfBmoPattern.ps->ppal();
  919. }
  920. else
  921. {
  922. if (SurfBmoPattern.ps->iFormat() == po.iDitherFormat())
  923. {
  924. if (po.bIsPalManaged())
  925. {
  926. ppalSrcTmp = (PPALETTE) NULL;
  927. }
  928. else
  929. {
  930. ppalSrcTmp = po.ppalSurf();
  931. }
  932. }
  933. else if (SurfBmoPattern.ps->iFormat() == pebo->iMetaFormat())
  934. {
  935. // We can try to use palette from meta.
  936. ppalSrcTmp = pebo->palMeta().ppalGet();
  937. }
  938. else if (SurfBmoPattern.ps->iFormat() == BMF_8BPP)
  939. {
  940. if (po.bIsPalManaged())
  941. {
  942. ppalSrcTmp = (PPALETTE) NULL;
  943. }
  944. else
  945. {
  946. ppalSrcTmp = ppalDefaultSurface8bpp;
  947. }
  948. }
  949. else
  950. {
  951. if (po.bMetaDriver())
  952. ppalSrcTmp = (PPALETTE) NULL;
  953. else
  954. {
  955. WARNING("bGetRealizedBrush failed - bitmap not compatible with surface\n");
  956. return FALSE;
  957. }
  958. }
  959. }
  960. // Replace source palette with proper one which decided in above.
  961. palSrc.ppalSet(ppalSrcTmp);
  962. if (!exlo.bInitXlateObj(
  963. (bIcmBrush ? pebo->hcmXform() : NULL),
  964. (bIcmBrush ? pebo->lIcmMode() : DC_ICM_OFF),
  965. palSrc,
  966. palDest,
  967. pebo->palDC(),
  968. pebo->palDC(),
  969. pebo->crCurrentText(),
  970. pebo->crCurrentBack(),
  971. 0x00FFFFFF
  972. ))
  973. {
  974. WARNING("Failed to create an xlate pvGetRbrush\n");
  975. return (FALSE);
  976. }
  977. pxlo = exlo.pxlo();
  978. }
  979. }
  980. // Do the right thing if a pattern is provided
  981. if (SurfBmoPattern.bValid())
  982. {
  983. psoPattern = SurfBmoPattern.pSurfobj();
  984. }
  985. else
  986. {
  987. // Check for dithering
  988. if (SurfDimo.bValid())
  989. {
  990. psoPattern = SurfDimo.pSurfobj();
  991. }
  992. else
  993. psoPattern = (SURFOBJ *) NULL;
  994. }
  995. // Call off to driver to the RealizeBrush
  996. return((*pfnDrv) (pebo, pebo->psoTarg()->pSurfobj(),
  997. psoPattern, psoMask,
  998. pxlo,
  999. ulStyle));
  1000. }